blob: 477badbdf2d4cbf2b2e805da80e2d1625e5f750e [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;
Mitsuru Oshima12172ba2009-06-12 15:50:03 -070035import android.content.pm.PackageParser.Component;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.content.res.AssetManager;
37import 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;
51import android.os.Process;
52import android.os.RemoteException;
53import android.os.ServiceManager;
54import android.os.SystemClock;
55import android.util.AndroidRuntimeException;
56import android.util.Config;
57import android.util.DisplayMetrics;
58import android.util.EventLog;
59import android.util.Log;
60import android.view.Display;
61import android.view.View;
62import android.view.ViewDebug;
63import android.view.ViewManager;
64import android.view.Window;
65import android.view.WindowManager;
66import android.view.WindowManagerImpl;
67
68import com.android.internal.os.BinderInternal;
69import com.android.internal.os.RuntimeInit;
70import com.android.internal.util.ArrayUtils;
71
72import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
73
74import java.io.File;
75import java.io.FileDescriptor;
76import java.io.FileOutputStream;
77import java.io.PrintWriter;
78import java.lang.ref.WeakReference;
79import java.util.ArrayList;
80import java.util.HashMap;
81import java.util.Iterator;
82import java.util.List;
83import java.util.Locale;
84import java.util.Map;
85import java.util.TimeZone;
86import java.util.regex.Pattern;
87
88final class IntentReceiverLeaked extends AndroidRuntimeException {
89 public IntentReceiverLeaked(String msg) {
90 super(msg);
91 }
92}
93
94final class ServiceConnectionLeaked extends AndroidRuntimeException {
95 public ServiceConnectionLeaked(String msg) {
96 super(msg);
97 }
98}
99
100final class SuperNotCalledException extends AndroidRuntimeException {
101 public SuperNotCalledException(String msg) {
102 super(msg);
103 }
104}
105
106/**
107 * This manages the execution of the main thread in an
108 * application process, scheduling and executing activities,
109 * broadcasts, and other operations on it as the activity
110 * manager requests.
111 *
112 * {@hide}
113 */
114public final class ActivityThread {
115 private static final String TAG = "ActivityThread";
116 private static final boolean DEBUG = false;
117 private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
118 private static final boolean DEBUG_BROADCAST = false;
Chris Tate8a7dc172009-03-24 20:11:42 -0700119 private static final boolean DEBUG_RESULTS = false;
Christopher Tate181fafa2009-05-14 11:12:14 -0700120 private static final boolean DEBUG_BACKUP = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
122 private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
123 private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
124 private static final int LOG_ON_PAUSE_CALLED = 30021;
125 private static final int LOG_ON_RESUME_CALLED = 30022;
126
127
128 public static final ActivityThread currentActivityThread() {
129 return (ActivityThread)sThreadLocal.get();
130 }
131
132 public static final String currentPackageName()
133 {
134 ActivityThread am = currentActivityThread();
135 return (am != null && am.mBoundApplication != null)
136 ? am.mBoundApplication.processName : null;
137 }
138
139 public static IPackageManager getPackageManager() {
140 if (sPackageManager != null) {
141 //Log.v("PackageManager", "returning cur default = " + sPackageManager);
142 return sPackageManager;
143 }
144 IBinder b = ServiceManager.getService("package");
145 //Log.v("PackageManager", "default service binder = " + b);
146 sPackageManager = IPackageManager.Stub.asInterface(b);
147 //Log.v("PackageManager", "default service = " + sPackageManager);
148 return sPackageManager;
149 }
150
151 DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
152 if (mDisplayMetrics != null && !forceUpdate) {
153 return mDisplayMetrics;
154 }
155 if (mDisplay == null) {
156 WindowManager wm = WindowManagerImpl.getDefault();
157 mDisplay = wm.getDefaultDisplay();
158 }
159 DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
160 mDisplay.getMetrics(metrics);
161 //Log.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
162 // + metrics.heightPixels + " den=" + metrics.density
163 // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
164 return metrics;
165 }
166
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700167 Resources getTopLevelResources(String appDir, PackageInfo pkgInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 synchronized (mPackages) {
169 //Log.w(TAG, "getTopLevelResources: " + appDir);
170 WeakReference<Resources> wr = mActiveResources.get(appDir);
171 Resources r = wr != null ? wr.get() : null;
172 if (r != null && r.getAssets().isUpToDate()) {
173 //Log.w(TAG, "Returning cached resources " + r + " " + appDir);
174 return r;
175 }
176
177 //if (r != null) {
178 // Log.w(TAG, "Throwing away out-of-date resources!!!! "
179 // + r + " " + appDir);
180 //}
181
182 AssetManager assets = new AssetManager();
183 if (assets.addAssetPath(appDir) == 0) {
184 return null;
185 }
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700186 ApplicationInfo appInfo;
187 try {
188 appInfo = getPackageManager().getApplicationInfo(
189 pkgInfo.getPackageName(),
190 PackageManager.GET_SUPPORTS_DENSITIES | PackageManager.GET_EXPANDABLE);
191 } catch (RemoteException e) {
192 throw new AssertionError(e);
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700193 }
Mitsuru Oshima58feea72009-05-11 15:54:27 -0700194 //Log.i(TAG, "Resource:" + appDir + ", display metrics=" + metrics);
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700195 DisplayMetrics metrics = getDisplayMetricsLocked(false);
196 r = new Resources(assets, metrics, getConfiguration(), appInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());
198 // XXX need to remove entries when weak references go away
199 mActiveResources.put(appDir, new WeakReference<Resources>(r));
200 return r;
201 }
202 }
203
204 final Handler getHandler() {
205 return mH;
206 }
207
208 public final static class PackageInfo {
209
210 private final ActivityThread mActivityThread;
211 private final ApplicationInfo mApplicationInfo;
212 private final String mPackageName;
213 private final String mAppDir;
214 private final String mResDir;
215 private final String[] mSharedLibraries;
216 private final String mDataDir;
217 private final File mDataDirFile;
218 private final ClassLoader mBaseClassLoader;
219 private final boolean mSecurityViolation;
220 private final boolean mIncludeCode;
221 private Resources mResources;
222 private ClassLoader mClassLoader;
223 private Application mApplication;
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
226 = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
227 private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mUnregisteredReceivers
228 = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
229 private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mServices
230 = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
231 private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mUnboundServices
232 = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
233
234 int mClientCount = 0;
235
236 public PackageInfo(ActivityThread activityThread, ApplicationInfo aInfo,
237 ActivityThread mainThread, ClassLoader baseLoader,
238 boolean securityViolation, boolean includeCode) {
239 mActivityThread = activityThread;
240 mApplicationInfo = aInfo;
241 mPackageName = aInfo.packageName;
242 mAppDir = aInfo.sourceDir;
243 mResDir = aInfo.uid == Process.myUid() ? aInfo.sourceDir
244 : aInfo.publicSourceDir;
245 mSharedLibraries = aInfo.sharedLibraryFiles;
246 mDataDir = aInfo.dataDir;
247 mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
248 mBaseClassLoader = baseLoader;
249 mSecurityViolation = securityViolation;
250 mIncludeCode = includeCode;
251
252 if (mAppDir == null) {
253 if (mSystemContext == null) {
254 mSystemContext =
255 ApplicationContext.createSystemContext(mainThread);
256 mSystemContext.getResources().updateConfiguration(
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700257 mainThread.getConfiguration(),
258 mainThread.getDisplayMetricsLocked(false));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 //Log.i(TAG, "Created system resources "
260 // + mSystemContext.getResources() + ": "
261 // + mSystemContext.getResources().getConfiguration());
262 }
263 mClassLoader = mSystemContext.getClassLoader();
264 mResources = mSystemContext.getResources();
265 }
266 }
267
268 public PackageInfo(ActivityThread activityThread, String name,
269 Context systemContext) {
270 mActivityThread = activityThread;
271 mApplicationInfo = new ApplicationInfo();
272 mApplicationInfo.packageName = name;
273 mPackageName = name;
274 mAppDir = null;
275 mResDir = null;
276 mSharedLibraries = null;
277 mDataDir = null;
278 mDataDirFile = null;
279 mBaseClassLoader = null;
280 mSecurityViolation = false;
281 mIncludeCode = true;
282 mClassLoader = systemContext.getClassLoader();
283 mResources = systemContext.getResources();
284 }
285
286 public String getPackageName() {
287 return mPackageName;
288 }
289
290 public boolean isSecurityViolation() {
291 return mSecurityViolation;
292 }
293
294 /**
295 * Gets the array of shared libraries that are listed as
296 * used by the given package.
297 *
298 * @param packageName the name of the package (note: not its
299 * file name)
300 * @return null-ok; the array of shared libraries, each one
301 * a fully-qualified path
302 */
303 private static String[] getLibrariesFor(String packageName) {
304 ApplicationInfo ai = null;
305 try {
306 ai = getPackageManager().getApplicationInfo(packageName,
307 PackageManager.GET_SHARED_LIBRARY_FILES);
308 } catch (RemoteException e) {
309 throw new AssertionError(e);
310 }
311
312 if (ai == null) {
313 return null;
314 }
315
316 return ai.sharedLibraryFiles;
317 }
318
319 /**
320 * Combines two arrays (of library names) such that they are
321 * concatenated in order but are devoid of duplicates. The
322 * result is a single string with the names of the libraries
323 * separated by colons, or <code>null</code> if both lists
324 * were <code>null</code> or empty.
325 *
326 * @param list1 null-ok; the first list
327 * @param list2 null-ok; the second list
328 * @return null-ok; the combination
329 */
330 private static String combineLibs(String[] list1, String[] list2) {
331 StringBuilder result = new StringBuilder(300);
332 boolean first = true;
333
334 if (list1 != null) {
335 for (String s : list1) {
336 if (first) {
337 first = false;
338 } else {
339 result.append(':');
340 }
341 result.append(s);
342 }
343 }
344
345 // Only need to check for duplicates if list1 was non-empty.
346 boolean dupCheck = !first;
347
348 if (list2 != null) {
349 for (String s : list2) {
350 if (dupCheck && ArrayUtils.contains(list1, s)) {
351 continue;
352 }
353
354 if (first) {
355 first = false;
356 } else {
357 result.append(':');
358 }
359 result.append(s);
360 }
361 }
362
363 return result.toString();
364 }
365
366 public ClassLoader getClassLoader() {
367 synchronized (this) {
368 if (mClassLoader != null) {
369 return mClassLoader;
370 }
371
372 if (mIncludeCode && !mPackageName.equals("android")) {
373 String zip = mAppDir;
374
375 /*
376 * The following is a bit of a hack to inject
377 * instrumentation into the system: If the app
378 * being started matches one of the instrumentation names,
379 * then we combine both the "instrumentation" and
380 * "instrumented" app into the path, along with the
381 * concatenation of both apps' shared library lists.
382 */
383
384 String instrumentationAppDir =
385 mActivityThread.mInstrumentationAppDir;
386 String instrumentationAppPackage =
387 mActivityThread.mInstrumentationAppPackage;
388 String instrumentedAppDir =
389 mActivityThread.mInstrumentedAppDir;
390 String[] instrumentationLibs = null;
391
392 if (mAppDir.equals(instrumentationAppDir)
393 || mAppDir.equals(instrumentedAppDir)) {
394 zip = instrumentationAppDir + ":" + instrumentedAppDir;
395 if (! instrumentedAppDir.equals(instrumentationAppDir)) {
396 instrumentationLibs =
397 getLibrariesFor(instrumentationAppPackage);
398 }
399 }
400
401 if ((mSharedLibraries != null) ||
402 (instrumentationLibs != null)) {
403 zip =
404 combineLibs(mSharedLibraries, instrumentationLibs)
405 + ':' + zip;
406 }
407
408 /*
409 * With all the combination done (if necessary, actually
410 * create the class loader.
411 */
412
413 if (localLOGV) Log.v(TAG, "Class path: " + zip);
414
415 mClassLoader =
416 ApplicationLoaders.getDefault().getClassLoader(
417 zip, mDataDir, mBaseClassLoader);
418 } else {
419 if (mBaseClassLoader == null) {
420 mClassLoader = ClassLoader.getSystemClassLoader();
421 } else {
422 mClassLoader = mBaseClassLoader;
423 }
424 }
425 return mClassLoader;
426 }
427 }
428
429 public String getAppDir() {
430 return mAppDir;
431 }
432
433 public String getResDir() {
434 return mResDir;
435 }
436
437 public String getDataDir() {
438 return mDataDir;
439 }
440
441 public File getDataDirFile() {
442 return mDataDirFile;
443 }
444
445 public AssetManager getAssets(ActivityThread mainThread) {
446 return getResources(mainThread).getAssets();
447 }
448
449 public Resources getResources(ActivityThread mainThread) {
450 if (mResources == null) {
Mitsuru Oshima9189cab2009-06-03 11:19:12 -0700451 mResources = mainThread.getTopLevelResources(mResDir, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 }
453 return mResources;
454 }
455
Christopher Tate181fafa2009-05-14 11:12:14 -0700456 public Application makeApplication(boolean forceDefaultAppClass) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 if (mApplication != null) {
458 return mApplication;
459 }
460
461 Application app = null;
462
463 String appClass = mApplicationInfo.className;
Christopher Tate181fafa2009-05-14 11:12:14 -0700464 if (forceDefaultAppClass || (appClass == null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 appClass = "android.app.Application";
466 }
467
468 try {
469 java.lang.ClassLoader cl = getClassLoader();
470 ApplicationContext appContext = new ApplicationContext();
471 appContext.init(this, null, mActivityThread);
472 app = mActivityThread.mInstrumentation.newApplication(
473 cl, appClass, appContext);
474 appContext.setOuterContext(app);
475 } catch (Exception e) {
476 if (!mActivityThread.mInstrumentation.onException(app, e)) {
477 throw new RuntimeException(
478 "Unable to instantiate application " + appClass
479 + ": " + e.toString(), e);
480 }
481 }
482 mActivityThread.mAllApplications.add(app);
483 return mApplication = app;
484 }
485
486 public void removeContextRegistrations(Context context,
487 String who, String what) {
488 HashMap<BroadcastReceiver, ReceiverDispatcher> rmap =
489 mReceivers.remove(context);
490 if (rmap != null) {
491 Iterator<ReceiverDispatcher> it = rmap.values().iterator();
492 while (it.hasNext()) {
493 ReceiverDispatcher rd = it.next();
494 IntentReceiverLeaked leak = new IntentReceiverLeaked(
495 what + " " + who + " has leaked IntentReceiver "
496 + rd.getIntentReceiver() + " that was " +
497 "originally registered here. Are you missing a " +
498 "call to unregisterReceiver()?");
499 leak.setStackTrace(rd.getLocation().getStackTrace());
500 Log.e(TAG, leak.getMessage(), leak);
501 try {
502 ActivityManagerNative.getDefault().unregisterReceiver(
503 rd.getIIntentReceiver());
504 } catch (RemoteException e) {
505 // system crashed, nothing we can do
506 }
507 }
508 }
509 mUnregisteredReceivers.remove(context);
510 //Log.i(TAG, "Receiver registrations: " + mReceivers);
511 HashMap<ServiceConnection, ServiceDispatcher> smap =
512 mServices.remove(context);
513 if (smap != null) {
514 Iterator<ServiceDispatcher> it = smap.values().iterator();
515 while (it.hasNext()) {
516 ServiceDispatcher sd = it.next();
517 ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
518 what + " " + who + " has leaked ServiceConnection "
519 + sd.getServiceConnection() + " that was originally bound here");
520 leak.setStackTrace(sd.getLocation().getStackTrace());
521 Log.e(TAG, leak.getMessage(), leak);
522 try {
523 ActivityManagerNative.getDefault().unbindService(
524 sd.getIServiceConnection());
525 } catch (RemoteException e) {
526 // system crashed, nothing we can do
527 }
528 sd.doForget();
529 }
530 }
531 mUnboundServices.remove(context);
532 //Log.i(TAG, "Service registrations: " + mServices);
533 }
534
535 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
536 Context context, Handler handler,
537 Instrumentation instrumentation, boolean registered) {
538 synchronized (mReceivers) {
539 ReceiverDispatcher rd = null;
540 HashMap<BroadcastReceiver, ReceiverDispatcher> map = null;
541 if (registered) {
542 map = mReceivers.get(context);
543 if (map != null) {
544 rd = map.get(r);
545 }
546 }
547 if (rd == null) {
548 rd = new ReceiverDispatcher(r, context, handler,
549 instrumentation, registered);
550 if (registered) {
551 if (map == null) {
552 map = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
553 mReceivers.put(context, map);
554 }
555 map.put(r, rd);
556 }
557 } else {
558 rd.validate(context, handler);
559 }
560 return rd.getIIntentReceiver();
561 }
562 }
563
564 public IIntentReceiver forgetReceiverDispatcher(Context context,
565 BroadcastReceiver r) {
566 synchronized (mReceivers) {
567 HashMap<BroadcastReceiver, ReceiverDispatcher> map = mReceivers.get(context);
568 ReceiverDispatcher rd = null;
569 if (map != null) {
570 rd = map.get(r);
571 if (rd != null) {
572 map.remove(r);
573 if (map.size() == 0) {
574 mReceivers.remove(context);
575 }
576 if (r.getDebugUnregister()) {
577 HashMap<BroadcastReceiver, ReceiverDispatcher> holder
578 = mUnregisteredReceivers.get(context);
579 if (holder == null) {
580 holder = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
581 mUnregisteredReceivers.put(context, holder);
582 }
583 RuntimeException ex = new IllegalArgumentException(
584 "Originally unregistered here:");
585 ex.fillInStackTrace();
586 rd.setUnregisterLocation(ex);
587 holder.put(r, rd);
588 }
589 return rd.getIIntentReceiver();
590 }
591 }
592 HashMap<BroadcastReceiver, ReceiverDispatcher> holder
593 = mUnregisteredReceivers.get(context);
594 if (holder != null) {
595 rd = holder.get(r);
596 if (rd != null) {
597 RuntimeException ex = rd.getUnregisterLocation();
598 throw new IllegalArgumentException(
599 "Unregistering Receiver " + r
600 + " that was already unregistered", ex);
601 }
602 }
603 if (context == null) {
604 throw new IllegalStateException("Unbinding Receiver " + r
605 + " from Context that is no longer in use: " + context);
606 } else {
607 throw new IllegalArgumentException("Receiver not registered: " + r);
608 }
609
610 }
611 }
612
613 static final class ReceiverDispatcher {
614
615 final static class InnerReceiver extends IIntentReceiver.Stub {
616 final WeakReference<ReceiverDispatcher> mDispatcher;
617 final ReceiverDispatcher mStrongRef;
618
619 InnerReceiver(ReceiverDispatcher rd, boolean strong) {
620 mDispatcher = new WeakReference<ReceiverDispatcher>(rd);
621 mStrongRef = strong ? rd : null;
622 }
623 public void performReceive(Intent intent, int resultCode,
624 String data, Bundle extras, boolean ordered) {
625 ReceiverDispatcher rd = mDispatcher.get();
626 if (DEBUG_BROADCAST) {
627 int seq = intent.getIntExtra("seq", -1);
628 Log.i(TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
629 + " to " + rd);
630 }
631 if (rd != null) {
632 rd.performReceive(intent, resultCode, data, extras, ordered);
633 }
634 }
635 }
636
637 final IIntentReceiver.Stub mIIntentReceiver;
638 final BroadcastReceiver mReceiver;
639 final Context mContext;
640 final Handler mActivityThread;
641 final Instrumentation mInstrumentation;
642 final boolean mRegistered;
643 final IntentReceiverLeaked mLocation;
644 RuntimeException mUnregisterLocation;
645
646 final class Args implements Runnable {
647 private Intent mCurIntent;
648 private int mCurCode;
649 private String mCurData;
650 private Bundle mCurMap;
651 private boolean mCurOrdered;
652
653 public void run() {
654 BroadcastReceiver receiver = mReceiver;
655 if (DEBUG_BROADCAST) {
656 int seq = mCurIntent.getIntExtra("seq", -1);
657 Log.i(TAG, "Dispathing broadcast " + mCurIntent.getAction() + " seq=" + seq
658 + " to " + mReceiver);
659 }
660 if (receiver == null) {
661 return;
662 }
663
664 IActivityManager mgr = ActivityManagerNative.getDefault();
665 Intent intent = mCurIntent;
666 mCurIntent = null;
667 try {
668 ClassLoader cl = mReceiver.getClass().getClassLoader();
669 intent.setExtrasClassLoader(cl);
670 if (mCurMap != null) {
671 mCurMap.setClassLoader(cl);
672 }
673 receiver.setOrderedHint(true);
674 receiver.setResult(mCurCode, mCurData, mCurMap);
675 receiver.clearAbortBroadcast();
676 receiver.setOrderedHint(mCurOrdered);
677 receiver.onReceive(mContext, intent);
678 } catch (Exception e) {
679 if (mRegistered && mCurOrdered) {
680 try {
681 mgr.finishReceiver(mIIntentReceiver,
682 mCurCode, mCurData, mCurMap, false);
683 } catch (RemoteException ex) {
684 }
685 }
686 if (mInstrumentation == null ||
687 !mInstrumentation.onException(mReceiver, e)) {
688 throw new RuntimeException(
689 "Error receiving broadcast " + intent
690 + " in " + mReceiver, e);
691 }
692 }
693 if (mRegistered && mCurOrdered) {
694 try {
695 mgr.finishReceiver(mIIntentReceiver,
696 receiver.getResultCode(),
697 receiver.getResultData(),
698 receiver.getResultExtras(false),
699 receiver.getAbortBroadcast());
700 } catch (RemoteException ex) {
701 }
702 }
703 }
704 }
705
706 ReceiverDispatcher(BroadcastReceiver receiver, Context context,
707 Handler activityThread, Instrumentation instrumentation,
708 boolean registered) {
709 if (activityThread == null) {
710 throw new NullPointerException("Handler must not be null");
711 }
712
713 mIIntentReceiver = new InnerReceiver(this, !registered);
714 mReceiver = receiver;
715 mContext = context;
716 mActivityThread = activityThread;
717 mInstrumentation = instrumentation;
718 mRegistered = registered;
719 mLocation = new IntentReceiverLeaked(null);
720 mLocation.fillInStackTrace();
721 }
722
723 void validate(Context context, Handler activityThread) {
724 if (mContext != context) {
725 throw new IllegalStateException(
726 "Receiver " + mReceiver +
727 " registered with differing Context (was " +
728 mContext + " now " + context + ")");
729 }
730 if (mActivityThread != activityThread) {
731 throw new IllegalStateException(
732 "Receiver " + mReceiver +
733 " registered with differing handler (was " +
734 mActivityThread + " now " + activityThread + ")");
735 }
736 }
737
738 IntentReceiverLeaked getLocation() {
739 return mLocation;
740 }
741
742 BroadcastReceiver getIntentReceiver() {
743 return mReceiver;
744 }
745
746 IIntentReceiver getIIntentReceiver() {
747 return mIIntentReceiver;
748 }
749
750 void setUnregisterLocation(RuntimeException ex) {
751 mUnregisterLocation = ex;
752 }
753
754 RuntimeException getUnregisterLocation() {
755 return mUnregisterLocation;
756 }
757
758 public void performReceive(Intent intent, int resultCode,
759 String data, Bundle extras, boolean ordered) {
760 if (DEBUG_BROADCAST) {
761 int seq = intent.getIntExtra("seq", -1);
762 Log.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
763 + " to " + mReceiver);
764 }
765 Args args = new Args();
766 args.mCurIntent = intent;
767 args.mCurCode = resultCode;
768 args.mCurData = data;
769 args.mCurMap = extras;
770 args.mCurOrdered = ordered;
771 if (!mActivityThread.post(args)) {
772 if (mRegistered) {
773 IActivityManager mgr = ActivityManagerNative.getDefault();
774 try {
775 mgr.finishReceiver(mIIntentReceiver, args.mCurCode,
776 args.mCurData, args.mCurMap, false);
777 } catch (RemoteException ex) {
778 }
779 }
780 }
781 }
782
783 }
784
785 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
786 Context context, Handler handler, int flags) {
787 synchronized (mServices) {
788 ServiceDispatcher sd = null;
789 HashMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
790 if (map != null) {
791 sd = map.get(c);
792 }
793 if (sd == null) {
794 sd = new ServiceDispatcher(c, context, handler, flags);
795 if (map == null) {
796 map = new HashMap<ServiceConnection, ServiceDispatcher>();
797 mServices.put(context, map);
798 }
799 map.put(c, sd);
800 } else {
801 sd.validate(context, handler);
802 }
803 return sd.getIServiceConnection();
804 }
805 }
806
807 public final IServiceConnection forgetServiceDispatcher(Context context,
808 ServiceConnection c) {
809 synchronized (mServices) {
810 HashMap<ServiceConnection, ServiceDispatcher> map
811 = mServices.get(context);
812 ServiceDispatcher sd = null;
813 if (map != null) {
814 sd = map.get(c);
815 if (sd != null) {
816 map.remove(c);
817 sd.doForget();
818 if (map.size() == 0) {
819 mServices.remove(context);
820 }
821 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
822 HashMap<ServiceConnection, ServiceDispatcher> holder
823 = mUnboundServices.get(context);
824 if (holder == null) {
825 holder = new HashMap<ServiceConnection, ServiceDispatcher>();
826 mUnboundServices.put(context, holder);
827 }
828 RuntimeException ex = new IllegalArgumentException(
829 "Originally unbound here:");
830 ex.fillInStackTrace();
831 sd.setUnbindLocation(ex);
832 holder.put(c, sd);
833 }
834 return sd.getIServiceConnection();
835 }
836 }
837 HashMap<ServiceConnection, ServiceDispatcher> holder
838 = mUnboundServices.get(context);
839 if (holder != null) {
840 sd = holder.get(c);
841 if (sd != null) {
842 RuntimeException ex = sd.getUnbindLocation();
843 throw new IllegalArgumentException(
844 "Unbinding Service " + c
845 + " that was already unbound", ex);
846 }
847 }
848 if (context == null) {
849 throw new IllegalStateException("Unbinding Service " + c
850 + " from Context that is no longer in use: " + context);
851 } else {
852 throw new IllegalArgumentException("Service not registered: " + c);
853 }
854 }
855 }
856
857 static final class ServiceDispatcher {
858 private final InnerConnection mIServiceConnection;
859 private final ServiceConnection mConnection;
860 private final Context mContext;
861 private final Handler mActivityThread;
862 private final ServiceConnectionLeaked mLocation;
863 private final int mFlags;
864
865 private RuntimeException mUnbindLocation;
866
867 private boolean mDied;
868
869 private static class ConnectionInfo {
870 IBinder binder;
871 IBinder.DeathRecipient deathMonitor;
872 }
873
874 private static class InnerConnection extends IServiceConnection.Stub {
875 final WeakReference<ServiceDispatcher> mDispatcher;
876
877 InnerConnection(ServiceDispatcher sd) {
878 mDispatcher = new WeakReference<ServiceDispatcher>(sd);
879 }
880
881 public void connected(ComponentName name, IBinder service) throws RemoteException {
882 ServiceDispatcher sd = mDispatcher.get();
883 if (sd != null) {
884 sd.connected(name, service);
885 }
886 }
887 }
888
889 private final HashMap<ComponentName, ConnectionInfo> mActiveConnections
890 = new HashMap<ComponentName, ConnectionInfo>();
891
892 ServiceDispatcher(ServiceConnection conn,
893 Context context, Handler activityThread, int flags) {
894 mIServiceConnection = new InnerConnection(this);
895 mConnection = conn;
896 mContext = context;
897 mActivityThread = activityThread;
898 mLocation = new ServiceConnectionLeaked(null);
899 mLocation.fillInStackTrace();
900 mFlags = flags;
901 }
902
903 void validate(Context context, Handler activityThread) {
904 if (mContext != context) {
905 throw new RuntimeException(
906 "ServiceConnection " + mConnection +
907 " registered with differing Context (was " +
908 mContext + " now " + context + ")");
909 }
910 if (mActivityThread != activityThread) {
911 throw new RuntimeException(
912 "ServiceConnection " + mConnection +
913 " registered with differing handler (was " +
914 mActivityThread + " now " + activityThread + ")");
915 }
916 }
917
918 void doForget() {
919 synchronized(this) {
920 Iterator<ConnectionInfo> it = mActiveConnections.values().iterator();
921 while (it.hasNext()) {
922 ConnectionInfo ci = it.next();
923 ci.binder.unlinkToDeath(ci.deathMonitor, 0);
924 }
925 mActiveConnections.clear();
926 }
927 }
928
929 ServiceConnectionLeaked getLocation() {
930 return mLocation;
931 }
932
933 ServiceConnection getServiceConnection() {
934 return mConnection;
935 }
936
937 IServiceConnection getIServiceConnection() {
938 return mIServiceConnection;
939 }
940
941 int getFlags() {
942 return mFlags;
943 }
944
945 void setUnbindLocation(RuntimeException ex) {
946 mUnbindLocation = ex;
947 }
948
949 RuntimeException getUnbindLocation() {
950 return mUnbindLocation;
951 }
952
953 public void connected(ComponentName name, IBinder service) {
954 if (mActivityThread != null) {
955 mActivityThread.post(new RunConnection(name, service, 0));
956 } else {
957 doConnected(name, service);
958 }
959 }
960
961 public void death(ComponentName name, IBinder service) {
962 ConnectionInfo old;
963
964 synchronized (this) {
965 mDied = true;
966 old = mActiveConnections.remove(name);
967 if (old == null || old.binder != service) {
968 // Death for someone different than who we last
969 // reported... just ignore it.
970 return;
971 }
972 old.binder.unlinkToDeath(old.deathMonitor, 0);
973 }
974
975 if (mActivityThread != null) {
976 mActivityThread.post(new RunConnection(name, service, 1));
977 } else {
978 doDeath(name, service);
979 }
980 }
981
982 public void doConnected(ComponentName name, IBinder service) {
983 ConnectionInfo old;
984 ConnectionInfo info;
985
986 synchronized (this) {
987 old = mActiveConnections.get(name);
988 if (old != null && old.binder == service) {
989 // Huh, already have this one. Oh well!
990 return;
991 }
992
993 if (service != null) {
994 // A new service is being connected... set it all up.
995 mDied = false;
996 info = new ConnectionInfo();
997 info.binder = service;
998 info.deathMonitor = new DeathMonitor(name, service);
999 try {
1000 service.linkToDeath(info.deathMonitor, 0);
1001 mActiveConnections.put(name, info);
1002 } catch (RemoteException e) {
1003 // This service was dead before we got it... just
1004 // don't do anything with it.
1005 mActiveConnections.remove(name);
1006 return;
1007 }
1008
1009 } else {
1010 // The named service is being disconnected... clean up.
1011 mActiveConnections.remove(name);
1012 }
1013
1014 if (old != null) {
1015 old.binder.unlinkToDeath(old.deathMonitor, 0);
1016 }
1017 }
1018
1019 // If there was an old service, it is not disconnected.
1020 if (old != null) {
1021 mConnection.onServiceDisconnected(name);
1022 }
1023 // If there is a new service, it is now connected.
1024 if (service != null) {
1025 mConnection.onServiceConnected(name, service);
1026 }
1027 }
1028
1029 public void doDeath(ComponentName name, IBinder service) {
1030 mConnection.onServiceDisconnected(name);
1031 }
1032
1033 private final class RunConnection implements Runnable {
1034 RunConnection(ComponentName name, IBinder service, int command) {
1035 mName = name;
1036 mService = service;
1037 mCommand = command;
1038 }
1039
1040 public void run() {
1041 if (mCommand == 0) {
1042 doConnected(mName, mService);
1043 } else if (mCommand == 1) {
1044 doDeath(mName, mService);
1045 }
1046 }
1047
1048 final ComponentName mName;
1049 final IBinder mService;
1050 final int mCommand;
1051 }
1052
1053 private final class DeathMonitor implements IBinder.DeathRecipient
1054 {
1055 DeathMonitor(ComponentName name, IBinder service) {
1056 mName = name;
1057 mService = service;
1058 }
1059
1060 public void binderDied() {
1061 death(mName, mService);
1062 }
1063
1064 final ComponentName mName;
1065 final IBinder mService;
1066 }
1067 }
1068 }
1069
1070 private static ApplicationContext mSystemContext = null;
1071
1072 private static final class ActivityRecord {
1073 IBinder token;
1074 Intent intent;
1075 Bundle state;
1076 Activity activity;
1077 Window window;
1078 Activity parent;
1079 String embeddedID;
1080 Object lastNonConfigurationInstance;
1081 HashMap<String,Object> lastNonConfigurationChildInstances;
1082 boolean paused;
1083 boolean stopped;
1084 boolean hideForNow;
1085 Configuration newConfig;
1086 ActivityRecord nextIdle;
1087
1088 ActivityInfo activityInfo;
1089 PackageInfo packageInfo;
1090
1091 List<ResultInfo> pendingResults;
1092 List<Intent> pendingIntents;
1093
1094 boolean startsNotResumed;
1095 boolean isForward;
1096
1097 ActivityRecord() {
1098 parent = null;
1099 embeddedID = null;
1100 paused = false;
1101 stopped = false;
1102 hideForNow = false;
1103 nextIdle = null;
1104 }
1105
1106 public String toString() {
1107 ComponentName componentName = intent.getComponent();
1108 return "ActivityRecord{"
1109 + Integer.toHexString(System.identityHashCode(this))
1110 + " token=" + token + " " + (componentName == null
1111 ? "no component name" : componentName.toShortString())
1112 + "}";
1113 }
1114 }
1115
1116 private final class ProviderRecord implements IBinder.DeathRecipient {
1117 final String mName;
1118 final IContentProvider mProvider;
1119 final ContentProvider mLocalProvider;
1120
1121 ProviderRecord(String name, IContentProvider provider,
1122 ContentProvider localProvider) {
1123 mName = name;
1124 mProvider = provider;
1125 mLocalProvider = localProvider;
1126 }
1127
1128 public void binderDied() {
1129 removeDeadProvider(mName, mProvider);
1130 }
1131 }
1132
1133 private static final class NewIntentData {
1134 List<Intent> intents;
1135 IBinder token;
1136 public String toString() {
1137 return "NewIntentData{intents=" + intents + " token=" + token + "}";
1138 }
1139 }
1140
1141 private static final class ReceiverData {
1142 Intent intent;
1143 ActivityInfo info;
1144 int resultCode;
1145 String resultData;
1146 Bundle resultExtras;
1147 boolean sync;
1148 boolean resultAbort;
1149 public String toString() {
1150 return "ReceiverData{intent=" + intent + " packageName=" +
1151 info.packageName + " resultCode=" + resultCode
1152 + " resultData=" + resultData + " resultExtras=" + resultExtras + "}";
1153 }
1154 }
1155
Christopher Tate181fafa2009-05-14 11:12:14 -07001156 private static final class CreateBackupAgentData {
1157 ApplicationInfo appInfo;
1158 int backupMode;
1159 public String toString() {
1160 return "CreateBackupAgentData{appInfo=" + appInfo
1161 + " backupAgent=" + appInfo.backupAgentName
1162 + " mode=" + backupMode + "}";
1163 }
1164 }
1165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 private static final class CreateServiceData {
1167 IBinder token;
1168 ServiceInfo info;
1169 Intent intent;
1170 public String toString() {
1171 return "CreateServiceData{token=" + token + " className="
1172 + info.name + " packageName=" + info.packageName
1173 + " intent=" + intent + "}";
1174 }
1175 }
1176
1177 private static final class BindServiceData {
1178 IBinder token;
1179 Intent intent;
1180 boolean rebind;
1181 public String toString() {
1182 return "BindServiceData{token=" + token + " intent=" + intent + "}";
1183 }
1184 }
1185
1186 private static final class ServiceArgsData {
1187 IBinder token;
1188 int startId;
1189 Intent args;
1190 public String toString() {
1191 return "ServiceArgsData{token=" + token + " startId=" + startId
1192 + " args=" + args + "}";
1193 }
1194 }
1195
1196 private static final class AppBindData {
1197 PackageInfo info;
1198 String processName;
1199 ApplicationInfo appInfo;
1200 List<ProviderInfo> providers;
1201 ComponentName instrumentationName;
1202 String profileFile;
1203 Bundle instrumentationArgs;
1204 IInstrumentationWatcher instrumentationWatcher;
1205 int debugMode;
Christopher Tate181fafa2009-05-14 11:12:14 -07001206 boolean restrictedBackupMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 Configuration config;
1208 boolean handlingProfiling;
1209 public String toString() {
1210 return "AppBindData{appInfo=" + appInfo + "}";
1211 }
1212 }
1213
1214 private static final class DumpServiceInfo {
1215 FileDescriptor fd;
1216 IBinder service;
1217 String[] args;
1218 boolean dumped;
1219 }
1220
1221 private static final class ResultData {
1222 IBinder token;
1223 List<ResultInfo> results;
1224 public String toString() {
1225 return "ResultData{token=" + token + " results" + results + "}";
1226 }
1227 }
1228
1229 private static final class ContextCleanupInfo {
1230 ApplicationContext context;
1231 String what;
1232 String who;
1233 }
1234
1235 private final class ApplicationThread extends ApplicationThreadNative {
1236 private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
1237 private static final String ONE_COUNT_COLUMN = "%17s %8d";
1238 private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
1239
1240 // Formatting for checkin service - update version if row format changes
1241 private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
1242
1243 public final void schedulePauseActivity(IBinder token, boolean finished,
1244 boolean userLeaving, int configChanges) {
1245 queueOrSendMessage(
1246 finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
1247 token,
1248 (userLeaving ? 1 : 0),
1249 configChanges);
1250 }
1251
1252 public final void scheduleStopActivity(IBinder token, boolean showWindow,
1253 int configChanges) {
1254 queueOrSendMessage(
1255 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
1256 token, 0, configChanges);
1257 }
1258
1259 public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
1260 queueOrSendMessage(
1261 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
1262 token);
1263 }
1264
1265 public final void scheduleResumeActivity(IBinder token, boolean isForward) {
1266 queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
1267 }
1268
1269 public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
1270 ResultData res = new ResultData();
1271 res.token = token;
1272 res.results = results;
1273 queueOrSendMessage(H.SEND_RESULT, res);
1274 }
1275
1276 // we use token to identify this activity without having to send the
1277 // activity itself back to the activity manager. (matters more with ipc)
1278 public final void scheduleLaunchActivity(Intent intent, IBinder token,
1279 ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
1280 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
1281 ActivityRecord r = new ActivityRecord();
1282
1283 r.token = token;
1284 r.intent = intent;
1285 r.activityInfo = info;
1286 r.state = state;
1287
1288 r.pendingResults = pendingResults;
1289 r.pendingIntents = pendingNewIntents;
1290
1291 r.startsNotResumed = notResumed;
1292 r.isForward = isForward;
1293
1294 queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
1295 }
1296
1297 public final void scheduleRelaunchActivity(IBinder token,
1298 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
1299 int configChanges, boolean notResumed) {
1300 ActivityRecord r = new ActivityRecord();
1301
1302 r.token = token;
1303 r.pendingResults = pendingResults;
1304 r.pendingIntents = pendingNewIntents;
1305 r.startsNotResumed = notResumed;
1306
1307 synchronized (mRelaunchingActivities) {
1308 mRelaunchingActivities.add(r);
1309 }
1310
1311 queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
1312 }
1313
1314 public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
1315 NewIntentData data = new NewIntentData();
1316 data.intents = intents;
1317 data.token = token;
1318
1319 queueOrSendMessage(H.NEW_INTENT, data);
1320 }
1321
1322 public final void scheduleDestroyActivity(IBinder token, boolean finishing,
1323 int configChanges) {
1324 queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
1325 configChanges);
1326 }
1327
1328 public final void scheduleReceiver(Intent intent, ActivityInfo info,
1329 int resultCode, String data, Bundle extras, boolean sync) {
1330 ReceiverData r = new ReceiverData();
1331
1332 r.intent = intent;
1333 r.info = info;
1334 r.resultCode = resultCode;
1335 r.resultData = data;
1336 r.resultExtras = extras;
1337 r.sync = sync;
1338
1339 queueOrSendMessage(H.RECEIVER, r);
1340 }
1341
Christopher Tate181fafa2009-05-14 11:12:14 -07001342 public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) {
1343 CreateBackupAgentData d = new CreateBackupAgentData();
1344 d.appInfo = app;
1345 d.backupMode = backupMode;
1346
1347 queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
1348 }
1349
1350 public final void scheduleDestroyBackupAgent(ApplicationInfo app) {
1351 CreateBackupAgentData d = new CreateBackupAgentData();
1352 d.appInfo = app;
1353
1354 queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
1355 }
1356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 public final void scheduleCreateService(IBinder token,
1358 ServiceInfo info) {
1359 CreateServiceData s = new CreateServiceData();
1360 s.token = token;
1361 s.info = info;
1362
1363 queueOrSendMessage(H.CREATE_SERVICE, s);
1364 }
1365
1366 public final void scheduleBindService(IBinder token, Intent intent,
1367 boolean rebind) {
1368 BindServiceData s = new BindServiceData();
1369 s.token = token;
1370 s.intent = intent;
1371 s.rebind = rebind;
1372
1373 queueOrSendMessage(H.BIND_SERVICE, s);
1374 }
1375
1376 public final void scheduleUnbindService(IBinder token, Intent intent) {
1377 BindServiceData s = new BindServiceData();
1378 s.token = token;
1379 s.intent = intent;
1380
1381 queueOrSendMessage(H.UNBIND_SERVICE, s);
1382 }
1383
1384 public final void scheduleServiceArgs(IBinder token, int startId,
1385 Intent args) {
1386 ServiceArgsData s = new ServiceArgsData();
1387 s.token = token;
1388 s.startId = startId;
1389 s.args = args;
1390
1391 queueOrSendMessage(H.SERVICE_ARGS, s);
1392 }
1393
1394 public final void scheduleStopService(IBinder token) {
1395 queueOrSendMessage(H.STOP_SERVICE, token);
1396 }
1397
1398 public final void bindApplication(String processName,
1399 ApplicationInfo appInfo, List<ProviderInfo> providers,
1400 ComponentName instrumentationName, String profileFile,
1401 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
Christopher Tate181fafa2009-05-14 11:12:14 -07001402 int debugMode, boolean isRestrictedBackupMode, Configuration config,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 Map<String, IBinder> services) {
1404 Process.setArgV0(processName);
1405
1406 if (services != null) {
1407 // Setup the service cache in the ServiceManager
1408 ServiceManager.initServiceCache(services);
1409 }
1410
1411 AppBindData data = new AppBindData();
1412 data.processName = processName;
1413 data.appInfo = appInfo;
1414 data.providers = providers;
1415 data.instrumentationName = instrumentationName;
1416 data.profileFile = profileFile;
1417 data.instrumentationArgs = instrumentationArgs;
1418 data.instrumentationWatcher = instrumentationWatcher;
1419 data.debugMode = debugMode;
Christopher Tate181fafa2009-05-14 11:12:14 -07001420 data.restrictedBackupMode = isRestrictedBackupMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 data.config = config;
1422 queueOrSendMessage(H.BIND_APPLICATION, data);
1423 }
1424
1425 public final void scheduleExit() {
1426 queueOrSendMessage(H.EXIT_APPLICATION, null);
1427 }
1428
1429 public void requestThumbnail(IBinder token) {
1430 queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
1431 }
1432
1433 public void scheduleConfigurationChanged(Configuration config) {
1434 synchronized (mRelaunchingActivities) {
1435 mPendingConfiguration = config;
1436 }
1437 queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
1438 }
1439
1440 public void updateTimeZone() {
1441 TimeZone.setDefault(null);
1442 }
1443
1444 public void processInBackground() {
1445 mH.removeMessages(H.GC_WHEN_IDLE);
1446 mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
1447 }
1448
1449 public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
1450 DumpServiceInfo data = new DumpServiceInfo();
1451 data.fd = fd;
1452 data.service = servicetoken;
1453 data.args = args;
1454 data.dumped = false;
1455 queueOrSendMessage(H.DUMP_SERVICE, data);
1456 synchronized (data) {
1457 while (!data.dumped) {
1458 try {
1459 data.wait();
1460 } catch (InterruptedException e) {
1461 // no need to do anything here, we will keep waiting until
1462 // dumped is set
1463 }
1464 }
1465 }
1466 }
1467
1468 // This function exists to make sure all receiver dispatching is
1469 // correctly ordered, since these are one-way calls and the binder driver
1470 // applies transaction ordering per object for such calls.
1471 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
1472 int resultCode, String dataStr, Bundle extras, boolean ordered)
1473 throws RemoteException {
1474 receiver.performReceive(intent, resultCode, dataStr, extras, ordered);
1475 }
1476
1477 public void scheduleLowMemory() {
1478 queueOrSendMessage(H.LOW_MEMORY, null);
1479 }
1480
1481 public void scheduleActivityConfigurationChanged(IBinder token) {
1482 queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
1483 }
1484
1485 public void requestPss() {
1486 try {
1487 ActivityManagerNative.getDefault().reportPss(this,
1488 (int)Process.getPss(Process.myPid()));
1489 } catch (RemoteException e) {
1490 }
1491 }
1492
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001493 public void profilerControl(boolean start, String path) {
1494 queueOrSendMessage(H.PROFILER_CONTROL, path, start ? 1 : 0);
1495 }
1496
Dianne Hackborn06de2ea2009-05-21 12:56:43 -07001497 public void setSchedulingGroup(int group) {
1498 // Note: do this immediately, since going into the foreground
1499 // should happen regardless of what pending work we have to do
1500 // and the activity manager will wait for us to report back that
1501 // we are done before sending us to the background.
1502 try {
1503 Process.setProcessGroup(Process.myPid(), group);
1504 } catch (Exception e) {
1505 Log.w(TAG, "Failed setting process group to " + group, e);
1506 }
1507 }
1508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 @Override
1510 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1511 long nativeMax = Debug.getNativeHeapSize() / 1024;
1512 long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
1513 long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
1514
1515 Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
1516 Debug.getMemoryInfo(memInfo);
1517
1518 final int nativeShared = memInfo.nativeSharedDirty;
1519 final int dalvikShared = memInfo.dalvikSharedDirty;
1520 final int otherShared = memInfo.otherSharedDirty;
1521
1522 final int nativePrivate = memInfo.nativePrivateDirty;
1523 final int dalvikPrivate = memInfo.dalvikPrivateDirty;
1524 final int otherPrivate = memInfo.otherPrivateDirty;
1525
1526 Runtime runtime = Runtime.getRuntime();
1527
1528 long dalvikMax = runtime.totalMemory() / 1024;
1529 long dalvikFree = runtime.freeMemory() / 1024;
1530 long dalvikAllocated = dalvikMax - dalvikFree;
1531 long viewInstanceCount = ViewDebug.getViewInstanceCount();
1532 long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount();
1533 long appContextInstanceCount = ApplicationContext.getInstanceCount();
1534 long activityInstanceCount = Activity.getInstanceCount();
1535 int globalAssetCount = AssetManager.getGlobalAssetCount();
1536 int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
1537 int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
1538 int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
1539 int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
1540 int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount();
1541 long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
1542 SQLiteDebug.PagerStats stats = new SQLiteDebug.PagerStats();
1543 SQLiteDebug.getPagerStats(stats);
1544
1545 // Check to see if we were called by checkin server. If so, print terse format.
1546 boolean doCheckinFormat = false;
1547 if (args != null) {
1548 for (String arg : args) {
1549 if ("-c".equals(arg)) doCheckinFormat = true;
1550 }
1551 }
1552
1553 // For checkin, we print one long comma-separated list of values
1554 if (doCheckinFormat) {
1555 // NOTE: if you change anything significant below, also consider changing
1556 // ACTIVITY_THREAD_CHECKIN_VERSION.
1557 String processName = (mBoundApplication != null)
1558 ? mBoundApplication.processName : "unknown";
1559
1560 // Header
1561 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
1562 pw.print(Process.myPid()); pw.print(',');
1563 pw.print(processName); pw.print(',');
1564
1565 // Heap info - max
1566 pw.print(nativeMax); pw.print(',');
1567 pw.print(dalvikMax); pw.print(',');
1568 pw.print("N/A,");
1569 pw.print(nativeMax + dalvikMax); pw.print(',');
1570
1571 // Heap info - allocated
1572 pw.print(nativeAllocated); pw.print(',');
1573 pw.print(dalvikAllocated); pw.print(',');
1574 pw.print("N/A,");
1575 pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
1576
1577 // Heap info - free
1578 pw.print(nativeFree); pw.print(',');
1579 pw.print(dalvikFree); pw.print(',');
1580 pw.print("N/A,");
1581 pw.print(nativeFree + dalvikFree); pw.print(',');
1582
1583 // Heap info - proportional set size
1584 pw.print(memInfo.nativePss); pw.print(',');
1585 pw.print(memInfo.dalvikPss); pw.print(',');
1586 pw.print(memInfo.otherPss); pw.print(',');
1587 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
1588
1589 // Heap info - shared
1590 pw.print(nativeShared); pw.print(',');
1591 pw.print(dalvikShared); pw.print(',');
1592 pw.print(otherShared); pw.print(',');
1593 pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
1594
1595 // Heap info - private
1596 pw.print(nativePrivate); pw.print(',');
1597 pw.print(dalvikPrivate); pw.print(',');
1598 pw.print(otherPrivate); pw.print(',');
1599 pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
1600
1601 // Object counts
1602 pw.print(viewInstanceCount); pw.print(',');
1603 pw.print(viewRootInstanceCount); pw.print(',');
1604 pw.print(appContextInstanceCount); pw.print(',');
1605 pw.print(activityInstanceCount); pw.print(',');
1606
1607 pw.print(globalAssetCount); pw.print(',');
1608 pw.print(globalAssetManagerCount); pw.print(',');
1609 pw.print(binderLocalObjectCount); pw.print(',');
1610 pw.print(binderProxyObjectCount); pw.print(',');
1611
1612 pw.print(binderDeathObjectCount); pw.print(',');
1613 pw.print(openSslSocketCount); pw.print(',');
1614
1615 // SQL
1616 pw.print(sqliteAllocated); pw.print(',');
1617 pw.print(stats.databaseBytes / 1024); pw.print(',');
1618 pw.print(stats.numPagers); pw.print(',');
1619 pw.print((stats.totalBytes - stats.referencedBytes) / 1024); pw.print(',');
1620 pw.print(stats.referencedBytes / 1024); pw.print('\n');
1621
1622 return;
1623 }
1624
1625 // otherwise, show human-readable format
1626 printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
1627 printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
1628 printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
1629 nativeAllocated + dalvikAllocated);
1630 printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
1631 nativeFree + dalvikFree);
1632
1633 printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
1634 memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
1635
1636 printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
1637 nativeShared + dalvikShared + otherShared);
1638 printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
1639 nativePrivate + dalvikPrivate + otherPrivate);
1640
1641 pw.println(" ");
1642 pw.println(" Objects");
1643 printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:",
1644 viewRootInstanceCount);
1645
1646 printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
1647 "Activities:", activityInstanceCount);
1648
1649 printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
1650 "AssetManagers:", globalAssetManagerCount);
1651
1652 printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
1653 "Proxy Binders:", binderProxyObjectCount);
1654 printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
1655
1656 printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
1657
1658 // SQLite mem info
1659 pw.println(" ");
1660 pw.println(" SQL");
1661 printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "dbFiles:",
1662 stats.databaseBytes / 1024);
1663 printRow(pw, TWO_COUNT_COLUMNS, "numPagers:", stats.numPagers, "inactivePageKB:",
1664 (stats.totalBytes - stats.referencedBytes) / 1024);
1665 printRow(pw, ONE_COUNT_COLUMN, "activePageKB:", stats.referencedBytes / 1024);
1666 }
1667
1668 private void printRow(PrintWriter pw, String format, Object...objs) {
1669 pw.println(String.format(format, objs));
1670 }
1671 }
1672
1673 private final class H extends Handler {
1674 public static final int LAUNCH_ACTIVITY = 100;
1675 public static final int PAUSE_ACTIVITY = 101;
1676 public static final int PAUSE_ACTIVITY_FINISHING= 102;
1677 public static final int STOP_ACTIVITY_SHOW = 103;
1678 public static final int STOP_ACTIVITY_HIDE = 104;
1679 public static final int SHOW_WINDOW = 105;
1680 public static final int HIDE_WINDOW = 106;
1681 public static final int RESUME_ACTIVITY = 107;
1682 public static final int SEND_RESULT = 108;
1683 public static final int DESTROY_ACTIVITY = 109;
1684 public static final int BIND_APPLICATION = 110;
1685 public static final int EXIT_APPLICATION = 111;
1686 public static final int NEW_INTENT = 112;
1687 public static final int RECEIVER = 113;
1688 public static final int CREATE_SERVICE = 114;
1689 public static final int SERVICE_ARGS = 115;
1690 public static final int STOP_SERVICE = 116;
1691 public static final int REQUEST_THUMBNAIL = 117;
1692 public static final int CONFIGURATION_CHANGED = 118;
1693 public static final int CLEAN_UP_CONTEXT = 119;
1694 public static final int GC_WHEN_IDLE = 120;
1695 public static final int BIND_SERVICE = 121;
1696 public static final int UNBIND_SERVICE = 122;
1697 public static final int DUMP_SERVICE = 123;
1698 public static final int LOW_MEMORY = 124;
1699 public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
1700 public static final int RELAUNCH_ACTIVITY = 126;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001701 public static final int PROFILER_CONTROL = 127;
Christopher Tate181fafa2009-05-14 11:12:14 -07001702 public static final int CREATE_BACKUP_AGENT = 128;
1703 public static final int DESTROY_BACKUP_AGENT = 129;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 String codeToString(int code) {
1705 if (localLOGV) {
1706 switch (code) {
1707 case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
1708 case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
1709 case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
1710 case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
1711 case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
1712 case SHOW_WINDOW: return "SHOW_WINDOW";
1713 case HIDE_WINDOW: return "HIDE_WINDOW";
1714 case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
1715 case SEND_RESULT: return "SEND_RESULT";
1716 case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
1717 case BIND_APPLICATION: return "BIND_APPLICATION";
1718 case EXIT_APPLICATION: return "EXIT_APPLICATION";
1719 case NEW_INTENT: return "NEW_INTENT";
1720 case RECEIVER: return "RECEIVER";
1721 case CREATE_SERVICE: return "CREATE_SERVICE";
1722 case SERVICE_ARGS: return "SERVICE_ARGS";
1723 case STOP_SERVICE: return "STOP_SERVICE";
1724 case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
1725 case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
1726 case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
1727 case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
1728 case BIND_SERVICE: return "BIND_SERVICE";
1729 case UNBIND_SERVICE: return "UNBIND_SERVICE";
1730 case DUMP_SERVICE: return "DUMP_SERVICE";
1731 case LOW_MEMORY: return "LOW_MEMORY";
1732 case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
1733 case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001734 case PROFILER_CONTROL: return "PROFILER_CONTROL";
Christopher Tate181fafa2009-05-14 11:12:14 -07001735 case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
1736 case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737 }
1738 }
1739 return "(unknown)";
1740 }
1741 public void handleMessage(Message msg) {
1742 switch (msg.what) {
1743 case LAUNCH_ACTIVITY: {
1744 ActivityRecord r = (ActivityRecord)msg.obj;
1745
1746 r.packageInfo = getPackageInfoNoCheck(
1747 r.activityInfo.applicationInfo);
Christopher Tateb70f3df2009-04-07 16:07:59 -07001748 handleLaunchActivity(r, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 } break;
1750 case RELAUNCH_ACTIVITY: {
1751 ActivityRecord r = (ActivityRecord)msg.obj;
1752 handleRelaunchActivity(r, msg.arg1);
1753 } break;
1754 case PAUSE_ACTIVITY:
1755 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
1756 break;
1757 case PAUSE_ACTIVITY_FINISHING:
1758 handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
1759 break;
1760 case STOP_ACTIVITY_SHOW:
1761 handleStopActivity((IBinder)msg.obj, true, msg.arg2);
1762 break;
1763 case STOP_ACTIVITY_HIDE:
1764 handleStopActivity((IBinder)msg.obj, false, msg.arg2);
1765 break;
1766 case SHOW_WINDOW:
1767 handleWindowVisibility((IBinder)msg.obj, true);
1768 break;
1769 case HIDE_WINDOW:
1770 handleWindowVisibility((IBinder)msg.obj, false);
1771 break;
1772 case RESUME_ACTIVITY:
1773 handleResumeActivity((IBinder)msg.obj, true,
1774 msg.arg1 != 0);
1775 break;
1776 case SEND_RESULT:
1777 handleSendResult((ResultData)msg.obj);
1778 break;
1779 case DESTROY_ACTIVITY:
1780 handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
1781 msg.arg2, false);
1782 break;
1783 case BIND_APPLICATION:
1784 AppBindData data = (AppBindData)msg.obj;
1785 handleBindApplication(data);
1786 break;
1787 case EXIT_APPLICATION:
1788 if (mInitialApplication != null) {
1789 mInitialApplication.onTerminate();
1790 }
1791 Looper.myLooper().quit();
1792 break;
1793 case NEW_INTENT:
1794 handleNewIntent((NewIntentData)msg.obj);
1795 break;
1796 case RECEIVER:
1797 handleReceiver((ReceiverData)msg.obj);
1798 break;
1799 case CREATE_SERVICE:
1800 handleCreateService((CreateServiceData)msg.obj);
1801 break;
1802 case BIND_SERVICE:
1803 handleBindService((BindServiceData)msg.obj);
1804 break;
1805 case UNBIND_SERVICE:
1806 handleUnbindService((BindServiceData)msg.obj);
1807 break;
1808 case SERVICE_ARGS:
1809 handleServiceArgs((ServiceArgsData)msg.obj);
1810 break;
1811 case STOP_SERVICE:
1812 handleStopService((IBinder)msg.obj);
1813 break;
1814 case REQUEST_THUMBNAIL:
1815 handleRequestThumbnail((IBinder)msg.obj);
1816 break;
1817 case CONFIGURATION_CHANGED:
1818 handleConfigurationChanged((Configuration)msg.obj);
1819 break;
1820 case CLEAN_UP_CONTEXT:
1821 ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
1822 cci.context.performFinalCleanup(cci.who, cci.what);
1823 break;
1824 case GC_WHEN_IDLE:
1825 scheduleGcIdler();
1826 break;
1827 case DUMP_SERVICE:
1828 handleDumpService((DumpServiceInfo)msg.obj);
1829 break;
1830 case LOW_MEMORY:
1831 handleLowMemory();
1832 break;
1833 case ACTIVITY_CONFIGURATION_CHANGED:
1834 handleActivityConfigurationChanged((IBinder)msg.obj);
1835 break;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08001836 case PROFILER_CONTROL:
1837 handleProfilerControl(msg.arg1 != 0, (String)msg.obj);
1838 break;
Christopher Tate181fafa2009-05-14 11:12:14 -07001839 case CREATE_BACKUP_AGENT:
1840 handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
1841 break;
1842 case DESTROY_BACKUP_AGENT:
1843 handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
1844 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845 }
1846 }
1847 }
1848
1849 private final class Idler implements MessageQueue.IdleHandler {
1850 public final boolean queueIdle() {
1851 ActivityRecord a = mNewActivities;
1852 if (a != null) {
1853 mNewActivities = null;
1854 IActivityManager am = ActivityManagerNative.getDefault();
1855 ActivityRecord prev;
1856 do {
1857 if (localLOGV) Log.v(
1858 TAG, "Reporting idle of " + a +
1859 " finished=" +
1860 (a.activity != null ? a.activity.mFinished : false));
1861 if (a.activity != null && !a.activity.mFinished) {
1862 try {
1863 am.activityIdle(a.token);
1864 } catch (RemoteException ex) {
1865 }
1866 }
1867 prev = a;
1868 a = a.nextIdle;
1869 prev.nextIdle = null;
1870 } while (a != null);
1871 }
1872 return false;
1873 }
1874 }
1875
1876 final class GcIdler implements MessageQueue.IdleHandler {
1877 public final boolean queueIdle() {
1878 doGcIfNeeded();
1879 return false;
1880 }
1881 }
1882
1883 static IPackageManager sPackageManager;
1884
1885 final ApplicationThread mAppThread = new ApplicationThread();
1886 final Looper mLooper = Looper.myLooper();
1887 final H mH = new H();
1888 final HashMap<IBinder, ActivityRecord> mActivities
1889 = new HashMap<IBinder, ActivityRecord>();
1890 // List of new activities (via ActivityRecord.nextIdle) that should
1891 // be reported when next we idle.
1892 ActivityRecord mNewActivities = null;
1893 // Number of activities that are currently visible on-screen.
1894 int mNumVisibleActivities = 0;
1895 final HashMap<IBinder, Service> mServices
1896 = new HashMap<IBinder, Service>();
1897 AppBindData mBoundApplication;
1898 Configuration mConfiguration;
1899 Application mInitialApplication;
1900 final ArrayList<Application> mAllApplications
1901 = new ArrayList<Application>();
Christopher Tate181fafa2009-05-14 11:12:14 -07001902 // set of instantiated backup agents, keyed by package name
1903 final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001904 static final ThreadLocal sThreadLocal = new ThreadLocal();
1905 Instrumentation mInstrumentation;
1906 String mInstrumentationAppDir = null;
1907 String mInstrumentationAppPackage = null;
1908 String mInstrumentedAppDir = null;
1909 boolean mSystemThread = false;
1910
1911 /**
1912 * Activities that are enqueued to be relaunched. This list is accessed
1913 * by multiple threads, so you must synchronize on it when accessing it.
1914 */
1915 final ArrayList<ActivityRecord> mRelaunchingActivities
1916 = new ArrayList<ActivityRecord>();
1917 Configuration mPendingConfiguration = null;
1918
1919 // These can be accessed by multiple threads; mPackages is the lock.
1920 // XXX For now we keep around information about all packages we have
1921 // seen, not removing entries from this map.
1922 final HashMap<String, WeakReference<PackageInfo>> mPackages
1923 = new HashMap<String, WeakReference<PackageInfo>>();
1924 final HashMap<String, WeakReference<PackageInfo>> mResourcePackages
1925 = new HashMap<String, WeakReference<PackageInfo>>();
1926 Display mDisplay = null;
1927 DisplayMetrics mDisplayMetrics = null;
1928 HashMap<String, WeakReference<Resources> > mActiveResources
1929 = new HashMap<String, WeakReference<Resources> >();
1930
1931 // The lock of mProviderMap protects the following variables.
1932 final HashMap<String, ProviderRecord> mProviderMap
1933 = new HashMap<String, ProviderRecord>();
1934 final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
1935 = new HashMap<IBinder, ProviderRefCount>();
1936 final HashMap<IBinder, ProviderRecord> mLocalProviders
1937 = new HashMap<IBinder, ProviderRecord>();
1938
1939 final GcIdler mGcIdler = new GcIdler();
1940 boolean mGcIdlerScheduled = false;
1941
1942 public final PackageInfo getPackageInfo(String packageName, int flags) {
1943 synchronized (mPackages) {
1944 WeakReference<PackageInfo> ref;
1945 if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
1946 ref = mPackages.get(packageName);
1947 } else {
1948 ref = mResourcePackages.get(packageName);
1949 }
1950 PackageInfo packageInfo = ref != null ? ref.get() : null;
1951 //Log.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
1952 if (packageInfo != null && (packageInfo.mResources == null
1953 || packageInfo.mResources.getAssets().isUpToDate())) {
1954 if (packageInfo.isSecurityViolation()
1955 && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
1956 throw new SecurityException(
1957 "Requesting code from " + packageName
1958 + " to be run in process "
1959 + mBoundApplication.processName
1960 + "/" + mBoundApplication.appInfo.uid);
1961 }
1962 return packageInfo;
1963 }
1964 }
1965
1966 ApplicationInfo ai = null;
1967 try {
1968 ai = getPackageManager().getApplicationInfo(packageName,
1969 PackageManager.GET_SHARED_LIBRARY_FILES);
1970 } catch (RemoteException e) {
1971 }
1972
1973 if (ai != null) {
1974 return getPackageInfo(ai, flags);
1975 }
1976
1977 return null;
1978 }
1979
1980 public final PackageInfo getPackageInfo(ApplicationInfo ai, int flags) {
1981 boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
1982 boolean securityViolation = includeCode && ai.uid != 0
1983 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
1984 ? ai.uid != mBoundApplication.appInfo.uid : true);
1985 if ((flags&(Context.CONTEXT_INCLUDE_CODE
1986 |Context.CONTEXT_IGNORE_SECURITY))
1987 == Context.CONTEXT_INCLUDE_CODE) {
1988 if (securityViolation) {
1989 String msg = "Requesting code from " + ai.packageName
1990 + " (with uid " + ai.uid + ")";
1991 if (mBoundApplication != null) {
1992 msg = msg + " to be run in process "
1993 + mBoundApplication.processName + " (with uid "
1994 + mBoundApplication.appInfo.uid + ")";
1995 }
1996 throw new SecurityException(msg);
1997 }
1998 }
1999 return getPackageInfo(ai, null, securityViolation, includeCode);
2000 }
2001
2002 public final PackageInfo getPackageInfoNoCheck(ApplicationInfo ai) {
2003 return getPackageInfo(ai, null, false, true);
2004 }
2005
2006 private final PackageInfo getPackageInfo(ApplicationInfo aInfo,
2007 ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
2008 synchronized (mPackages) {
2009 WeakReference<PackageInfo> ref;
2010 if (includeCode) {
2011 ref = mPackages.get(aInfo.packageName);
2012 } else {
2013 ref = mResourcePackages.get(aInfo.packageName);
2014 }
2015 PackageInfo packageInfo = ref != null ? ref.get() : null;
2016 if (packageInfo == null || (packageInfo.mResources != null
2017 && !packageInfo.mResources.getAssets().isUpToDate())) {
2018 if (localLOGV) Log.v(TAG, (includeCode ? "Loading code package "
2019 : "Loading resource-only package ") + aInfo.packageName
2020 + " (in " + (mBoundApplication != null
2021 ? mBoundApplication.processName : null)
2022 + ")");
2023 packageInfo =
2024 new PackageInfo(this, aInfo, this, baseLoader,
2025 securityViolation, includeCode &&
2026 (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
2027 if (includeCode) {
2028 mPackages.put(aInfo.packageName,
2029 new WeakReference<PackageInfo>(packageInfo));
2030 } else {
2031 mResourcePackages.put(aInfo.packageName,
2032 new WeakReference<PackageInfo>(packageInfo));
2033 }
2034 }
2035 return packageInfo;
2036 }
2037 }
2038
2039 public final boolean hasPackageInfo(String packageName) {
2040 synchronized (mPackages) {
2041 WeakReference<PackageInfo> ref;
2042 ref = mPackages.get(packageName);
2043 if (ref != null && ref.get() != null) {
2044 return true;
2045 }
2046 ref = mResourcePackages.get(packageName);
2047 if (ref != null && ref.get() != null) {
2048 return true;
2049 }
2050 return false;
2051 }
2052 }
2053
2054 ActivityThread() {
2055 }
2056
2057 public ApplicationThread getApplicationThread()
2058 {
2059 return mAppThread;
2060 }
2061
2062 public Instrumentation getInstrumentation()
2063 {
2064 return mInstrumentation;
2065 }
2066
2067 public Configuration getConfiguration() {
2068 return mConfiguration;
2069 }
2070
2071 public boolean isProfiling() {
2072 return mBoundApplication != null && mBoundApplication.profileFile != null;
2073 }
2074
2075 public String getProfileFilePath() {
2076 return mBoundApplication.profileFile;
2077 }
2078
2079 public Looper getLooper() {
2080 return mLooper;
2081 }
2082
2083 public Application getApplication() {
2084 return mInitialApplication;
2085 }
2086
2087 public ApplicationContext getSystemContext() {
2088 synchronized (this) {
2089 if (mSystemContext == null) {
2090 ApplicationContext context =
2091 ApplicationContext.createSystemContext(this);
2092 PackageInfo info = new PackageInfo(this, "android", context);
2093 context.init(info, null, this);
2094 context.getResources().updateConfiguration(
2095 getConfiguration(), getDisplayMetricsLocked(false));
2096 mSystemContext = context;
2097 //Log.i(TAG, "Created system resources " + context.getResources()
2098 // + ": " + context.getResources().getConfiguration());
2099 }
2100 }
2101 return mSystemContext;
2102 }
2103
2104 void scheduleGcIdler() {
2105 if (!mGcIdlerScheduled) {
2106 mGcIdlerScheduled = true;
2107 Looper.myQueue().addIdleHandler(mGcIdler);
2108 }
2109 mH.removeMessages(H.GC_WHEN_IDLE);
2110 }
2111
2112 void unscheduleGcIdler() {
2113 if (mGcIdlerScheduled) {
2114 mGcIdlerScheduled = false;
2115 Looper.myQueue().removeIdleHandler(mGcIdler);
2116 }
2117 mH.removeMessages(H.GC_WHEN_IDLE);
2118 }
2119
2120 void doGcIfNeeded() {
2121 mGcIdlerScheduled = false;
2122 final long now = SystemClock.uptimeMillis();
2123 //Log.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
2124 // + "m now=" + now);
2125 if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
2126 //Log.i(TAG, "**** WE DO, WE DO WANT TO GC!");
2127 BinderInternal.forceGc("bg");
2128 }
2129 }
2130
2131 public final ActivityInfo resolveActivityInfo(Intent intent) {
2132 ActivityInfo aInfo = intent.resolveActivityInfo(
2133 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
2134 if (aInfo == null) {
2135 // Throw an exception.
2136 Instrumentation.checkStartActivityResult(
2137 IActivityManager.START_CLASS_NOT_FOUND, intent);
2138 }
2139 return aInfo;
2140 }
2141
2142 public final Activity startActivityNow(Activity parent, String id,
2143 Intent intent, IBinder token, Bundle state) {
2144 ActivityInfo aInfo = resolveActivityInfo(intent);
2145 return startActivityNow(parent, id, intent, aInfo, token, state);
2146 }
2147
2148 public final Activity startActivityNow(Activity parent, String id,
2149 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state) {
2150 return startActivityNow(parent, id, intent, activityInfo, token, state, null);
2151 }
2152
2153 public final Activity startActivityNow(Activity parent, String id,
2154 Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
2155 Object lastNonConfigurationInstance) {
2156 ActivityRecord r = new ActivityRecord();
2157 r.token = token;
2158 r.intent = intent;
2159 r.state = state;
2160 r.parent = parent;
2161 r.embeddedID = id;
2162 r.activityInfo = activityInfo;
2163 r.lastNonConfigurationInstance = lastNonConfigurationInstance;
2164 if (localLOGV) {
2165 ComponentName compname = intent.getComponent();
2166 String name;
2167 if (compname != null) {
2168 name = compname.toShortString();
2169 } else {
2170 name = "(Intent " + intent + ").getComponent() returned null";
2171 }
2172 Log.v(TAG, "Performing launch: action=" + intent.getAction()
2173 + ", comp=" + name
2174 + ", token=" + token);
2175 }
Christopher Tateb70f3df2009-04-07 16:07:59 -07002176 return performLaunchActivity(r, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 }
2178
2179 public final Activity getActivity(IBinder token) {
2180 return mActivities.get(token).activity;
2181 }
2182
2183 public final void sendActivityResult(
2184 IBinder token, String id, int requestCode,
2185 int resultCode, Intent data) {
Chris Tate8a7dc172009-03-24 20:11:42 -07002186 if (DEBUG_RESULTS) Log.v(TAG, "sendActivityResult: id=" + id
2187 + " req=" + requestCode + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2189 list.add(new ResultInfo(id, requestCode, resultCode, data));
2190 mAppThread.scheduleSendResult(token, list);
2191 }
2192
2193 // if the thread hasn't started yet, we don't have the handler, so just
2194 // save the messages until we're ready.
2195 private final void queueOrSendMessage(int what, Object obj) {
2196 queueOrSendMessage(what, obj, 0, 0);
2197 }
2198
2199 private final void queueOrSendMessage(int what, Object obj, int arg1) {
2200 queueOrSendMessage(what, obj, arg1, 0);
2201 }
2202
2203 private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
2204 synchronized (this) {
2205 if (localLOGV) Log.v(
2206 TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
2207 + ": " + arg1 + " / " + obj);
2208 Message msg = Message.obtain();
2209 msg.what = what;
2210 msg.obj = obj;
2211 msg.arg1 = arg1;
2212 msg.arg2 = arg2;
2213 mH.sendMessage(msg);
2214 }
2215 }
2216
2217 final void scheduleContextCleanup(ApplicationContext context, String who,
2218 String what) {
2219 ContextCleanupInfo cci = new ContextCleanupInfo();
2220 cci.context = context;
2221 cci.who = who;
2222 cci.what = what;
2223 queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
2224 }
2225
Christopher Tateb70f3df2009-04-07 16:07:59 -07002226 private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
2228
2229 ActivityInfo aInfo = r.activityInfo;
2230 if (r.packageInfo == null) {
2231 r.packageInfo = getPackageInfo(aInfo.applicationInfo,
2232 Context.CONTEXT_INCLUDE_CODE);
2233 }
2234
2235 ComponentName component = r.intent.getComponent();
2236 if (component == null) {
2237 component = r.intent.resolveActivity(
2238 mInitialApplication.getPackageManager());
2239 r.intent.setComponent(component);
2240 }
2241
2242 if (r.activityInfo.targetActivity != null) {
2243 component = new ComponentName(r.activityInfo.packageName,
2244 r.activityInfo.targetActivity);
2245 }
2246
2247 Activity activity = null;
2248 try {
2249 java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
2250 activity = mInstrumentation.newActivity(
2251 cl, component.getClassName(), r.intent);
2252 r.intent.setExtrasClassLoader(cl);
2253 if (r.state != null) {
2254 r.state.setClassLoader(cl);
2255 }
2256 } catch (Exception e) {
2257 if (!mInstrumentation.onException(activity, e)) {
2258 throw new RuntimeException(
2259 "Unable to instantiate activity " + component
2260 + ": " + e.toString(), e);
2261 }
2262 }
2263
2264 try {
Christopher Tate181fafa2009-05-14 11:12:14 -07002265 Application app = r.packageInfo.makeApplication(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266
2267 if (localLOGV) Log.v(TAG, "Performing launch of " + r);
2268 if (localLOGV) Log.v(
2269 TAG, r + ": app=" + app
2270 + ", appName=" + app.getPackageName()
2271 + ", pkg=" + r.packageInfo.getPackageName()
2272 + ", comp=" + r.intent.getComponent().toShortString()
2273 + ", dir=" + r.packageInfo.getAppDir());
2274
2275 if (activity != null) {
2276 ApplicationContext appContext = new ApplicationContext();
2277 appContext.init(r.packageInfo, r.token, this);
2278 appContext.setOuterContext(activity);
2279 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
2280 Configuration config = new Configuration(mConfiguration);
2281 activity.attach(appContext, this, getInstrumentation(), r.token, app,
2282 r.intent, r.activityInfo, title, r.parent, r.embeddedID,
2283 r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances,
2284 config);
2285
Christopher Tateb70f3df2009-04-07 16:07:59 -07002286 if (customIntent != null) {
2287 activity.mIntent = customIntent;
2288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 r.lastNonConfigurationInstance = null;
2290 r.lastNonConfigurationChildInstances = null;
2291 activity.mStartedActivity = false;
2292 int theme = r.activityInfo.getThemeResource();
2293 if (theme != 0) {
2294 activity.setTheme(theme);
2295 }
2296
2297 activity.mCalled = false;
2298 mInstrumentation.callActivityOnCreate(activity, r.state);
2299 if (!activity.mCalled) {
2300 throw new SuperNotCalledException(
2301 "Activity " + r.intent.getComponent().toShortString() +
2302 " did not call through to super.onCreate()");
2303 }
2304 r.activity = activity;
2305 r.stopped = true;
2306 if (!r.activity.mFinished) {
2307 activity.performStart();
2308 r.stopped = false;
2309 }
2310 if (!r.activity.mFinished) {
2311 if (r.state != null) {
2312 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
2313 }
2314 }
2315 if (!r.activity.mFinished) {
2316 activity.mCalled = false;
2317 mInstrumentation.callActivityOnPostCreate(activity, r.state);
2318 if (!activity.mCalled) {
2319 throw new SuperNotCalledException(
2320 "Activity " + r.intent.getComponent().toShortString() +
2321 " did not call through to super.onPostCreate()");
2322 }
2323 }
2324 r.state = null;
2325 }
2326 r.paused = true;
2327
2328 mActivities.put(r.token, r);
2329
2330 } catch (SuperNotCalledException e) {
2331 throw e;
2332
2333 } catch (Exception e) {
2334 if (!mInstrumentation.onException(activity, e)) {
2335 throw new RuntimeException(
2336 "Unable to start activity " + component
2337 + ": " + e.toString(), e);
2338 }
2339 }
2340
2341 return activity;
2342 }
2343
Christopher Tateb70f3df2009-04-07 16:07:59 -07002344 private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 // If we are getting ready to gc after going to the background, well
2346 // we are back active so skip it.
2347 unscheduleGcIdler();
2348
2349 if (localLOGV) Log.v(
2350 TAG, "Handling launch of " + r);
Christopher Tateb70f3df2009-04-07 16:07:59 -07002351 Activity a = performLaunchActivity(r, customIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352
2353 if (a != null) {
2354 handleResumeActivity(r.token, false, r.isForward);
2355
2356 if (!r.activity.mFinished && r.startsNotResumed) {
2357 // The activity manager actually wants this one to start out
2358 // paused, because it needs to be visible but isn't in the
2359 // foreground. We accomplish this by going through the
2360 // normal startup (because activities expect to go through
2361 // onResume() the first time they run, before their window
2362 // is displayed), and then pausing it. However, in this case
2363 // we do -not- need to do the full pause cycle (of freezing
2364 // and such) because the activity manager assumes it can just
2365 // retain the current state it has.
2366 try {
2367 r.activity.mCalled = false;
2368 mInstrumentation.callActivityOnPause(r.activity);
2369 if (!r.activity.mCalled) {
2370 throw new SuperNotCalledException(
2371 "Activity " + r.intent.getComponent().toShortString() +
2372 " did not call through to super.onPause()");
2373 }
2374
2375 } catch (SuperNotCalledException e) {
2376 throw e;
2377
2378 } catch (Exception e) {
2379 if (!mInstrumentation.onException(r.activity, e)) {
2380 throw new RuntimeException(
2381 "Unable to pause activity "
2382 + r.intent.getComponent().toShortString()
2383 + ": " + e.toString(), e);
2384 }
2385 }
2386 r.paused = true;
2387 }
2388 } else {
2389 // If there was an error, for any reason, tell the activity
2390 // manager to stop us.
2391 try {
2392 ActivityManagerNative.getDefault()
2393 .finishActivity(r.token, Activity.RESULT_CANCELED, null);
2394 } catch (RemoteException ex) {
2395 }
2396 }
2397 }
2398
2399 private final void deliverNewIntents(ActivityRecord r,
2400 List<Intent> intents) {
2401 final int N = intents.size();
2402 for (int i=0; i<N; i++) {
2403 Intent intent = intents.get(i);
2404 intent.setExtrasClassLoader(r.activity.getClassLoader());
2405 mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2406 }
2407 }
2408
2409 public final void performNewIntents(IBinder token,
2410 List<Intent> intents) {
2411 ActivityRecord r = mActivities.get(token);
2412 if (r != null) {
2413 final boolean resumed = !r.paused;
2414 if (resumed) {
2415 mInstrumentation.callActivityOnPause(r.activity);
2416 }
2417 deliverNewIntents(r, intents);
2418 if (resumed) {
2419 mInstrumentation.callActivityOnResume(r.activity);
2420 }
2421 }
2422 }
2423
2424 private final void handleNewIntent(NewIntentData data) {
2425 performNewIntents(data.token, data.intents);
2426 }
2427
2428 private final void handleReceiver(ReceiverData data) {
2429 // If we are getting ready to gc after going to the background, well
2430 // we are back active so skip it.
2431 unscheduleGcIdler();
2432
2433 String component = data.intent.getComponent().getClassName();
2434
2435 PackageInfo packageInfo = getPackageInfoNoCheck(
2436 data.info.applicationInfo);
2437
2438 IActivityManager mgr = ActivityManagerNative.getDefault();
2439
2440 BroadcastReceiver receiver = null;
2441 try {
2442 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2443 data.intent.setExtrasClassLoader(cl);
2444 if (data.resultExtras != null) {
2445 data.resultExtras.setClassLoader(cl);
2446 }
2447 receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2448 } catch (Exception e) {
2449 try {
2450 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2451 data.resultData, data.resultExtras, data.resultAbort);
2452 } catch (RemoteException ex) {
2453 }
2454 throw new RuntimeException(
2455 "Unable to instantiate receiver " + component
2456 + ": " + e.toString(), e);
2457 }
2458
2459 try {
Christopher Tate181fafa2009-05-14 11:12:14 -07002460 Application app = packageInfo.makeApplication(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461
2462 if (localLOGV) Log.v(
2463 TAG, "Performing receive of " + data.intent
2464 + ": app=" + app
2465 + ", appName=" + app.getPackageName()
2466 + ", pkg=" + packageInfo.getPackageName()
2467 + ", comp=" + data.intent.getComponent().toShortString()
2468 + ", dir=" + packageInfo.getAppDir());
2469
2470 ApplicationContext context = (ApplicationContext)app.getBaseContext();
2471 receiver.setOrderedHint(true);
2472 receiver.setResult(data.resultCode, data.resultData,
2473 data.resultExtras);
2474 receiver.setOrderedHint(data.sync);
2475 receiver.onReceive(context.getReceiverRestrictedContext(),
2476 data.intent);
2477 } catch (Exception e) {
2478 try {
2479 mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
2480 data.resultData, data.resultExtras, data.resultAbort);
2481 } catch (RemoteException ex) {
2482 }
2483 if (!mInstrumentation.onException(receiver, e)) {
2484 throw new RuntimeException(
2485 "Unable to start receiver " + component
2486 + ": " + e.toString(), e);
2487 }
2488 }
2489
2490 try {
2491 if (data.sync) {
2492 mgr.finishReceiver(
2493 mAppThread.asBinder(), receiver.getResultCode(),
2494 receiver.getResultData(), receiver.getResultExtras(false),
2495 receiver.getAbortBroadcast());
2496 } else {
2497 mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
2498 }
2499 } catch (RemoteException ex) {
2500 }
2501 }
2502
Christopher Tate181fafa2009-05-14 11:12:14 -07002503 // Instantiate a BackupAgent and tell it that it's alive
2504 private final void handleCreateBackupAgent(CreateBackupAgentData data) {
2505 if (DEBUG_BACKUP) Log.v(TAG, "handleCreateBackupAgent: " + data);
2506
2507 // no longer idle; we have backup work to do
2508 unscheduleGcIdler();
2509
2510 // instantiate the BackupAgent class named in the manifest
2511 PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2512 String packageName = packageInfo.mPackageName;
2513 if (mBackupAgents.get(packageName) != null) {
2514 Log.d(TAG, "BackupAgent " + " for " + packageName
2515 + " already exists");
2516 return;
2517 }
2518
2519 BackupAgent agent = null;
2520 String classname = data.appInfo.backupAgentName;
2521 if (classname == null) {
2522 if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) {
2523 Log.e(TAG, "Attempted incremental backup but no defined agent for "
2524 + packageName);
2525 return;
2526 }
2527 classname = "android.app.FullBackupAgent";
2528 }
2529 try {
2530 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2531 agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance();
2532 } catch (Exception e) {
2533 throw new RuntimeException("Unable to instantiate backup agent "
2534 + data.appInfo.backupAgentName + ": " + e.toString(), e);
2535 }
2536
2537 // set up the agent's context
2538 try {
2539 if (DEBUG_BACKUP) Log.v(TAG, "Initializing BackupAgent "
2540 + data.appInfo.backupAgentName);
2541
2542 ApplicationContext context = new ApplicationContext();
2543 context.init(packageInfo, null, this);
2544 context.setOuterContext(agent);
2545 agent.attach(context);
2546 agent.onCreate();
2547
2548 // tell the OS that we're live now
2549 IBinder binder = agent.onBind();
2550 try {
2551 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
2552 } catch (RemoteException e) {
2553 // nothing to do.
2554 }
2555 mBackupAgents.put(packageName, agent);
2556 } catch (Exception e) {
2557 throw new RuntimeException("Unable to create BackupAgent "
2558 + data.appInfo.backupAgentName + ": " + e.toString(), e);
2559 }
2560 }
2561
2562 // Tear down a BackupAgent
2563 private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
2564 if (DEBUG_BACKUP) Log.v(TAG, "handleDestroyBackupAgent: " + data);
2565
2566 PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
2567 String packageName = packageInfo.mPackageName;
2568 BackupAgent agent = mBackupAgents.get(packageName);
2569 if (agent != null) {
2570 try {
2571 agent.onDestroy();
2572 } catch (Exception e) {
2573 Log.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
2574 e.printStackTrace();
2575 }
2576 mBackupAgents.remove(packageName);
2577 } else {
2578 Log.w(TAG, "Attempt to destroy unknown backup agent " + data);
2579 }
2580 }
2581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582 private final void handleCreateService(CreateServiceData data) {
2583 // If we are getting ready to gc after going to the background, well
2584 // we are back active so skip it.
2585 unscheduleGcIdler();
2586
2587 PackageInfo packageInfo = getPackageInfoNoCheck(
2588 data.info.applicationInfo);
2589 Service service = null;
2590 try {
2591 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2592 service = (Service) cl.loadClass(data.info.name).newInstance();
2593 } catch (Exception e) {
2594 if (!mInstrumentation.onException(service, e)) {
2595 throw new RuntimeException(
2596 "Unable to instantiate service " + data.info.name
2597 + ": " + e.toString(), e);
2598 }
2599 }
2600
2601 try {
2602 if (localLOGV) Log.v(TAG, "Creating service " + data.info.name);
2603
2604 ApplicationContext context = new ApplicationContext();
2605 context.init(packageInfo, null, this);
2606
Christopher Tate181fafa2009-05-14 11:12:14 -07002607 Application app = packageInfo.makeApplication(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 context.setOuterContext(service);
2609 service.attach(context, this, data.info.name, data.token, app,
2610 ActivityManagerNative.getDefault());
2611 service.onCreate();
2612 mServices.put(data.token, service);
2613 try {
2614 ActivityManagerNative.getDefault().serviceDoneExecuting(data.token);
2615 } catch (RemoteException e) {
2616 // nothing to do.
2617 }
2618 } catch (Exception e) {
2619 if (!mInstrumentation.onException(service, e)) {
2620 throw new RuntimeException(
2621 "Unable to create service " + data.info.name
2622 + ": " + e.toString(), e);
2623 }
2624 }
2625 }
2626
2627 private final void handleBindService(BindServiceData data) {
2628 Service s = mServices.get(data.token);
2629 if (s != null) {
2630 try {
2631 data.intent.setExtrasClassLoader(s.getClassLoader());
2632 try {
2633 if (!data.rebind) {
2634 IBinder binder = s.onBind(data.intent);
2635 ActivityManagerNative.getDefault().publishService(
2636 data.token, data.intent, binder);
2637 } else {
2638 s.onRebind(data.intent);
2639 ActivityManagerNative.getDefault().serviceDoneExecuting(
2640 data.token);
2641 }
2642 } catch (RemoteException ex) {
2643 }
2644 } catch (Exception e) {
2645 if (!mInstrumentation.onException(s, e)) {
2646 throw new RuntimeException(
2647 "Unable to bind to service " + s
2648 + " with " + data.intent + ": " + e.toString(), e);
2649 }
2650 }
2651 }
2652 }
2653
2654 private final void handleUnbindService(BindServiceData data) {
2655 Service s = mServices.get(data.token);
2656 if (s != null) {
2657 try {
2658 data.intent.setExtrasClassLoader(s.getClassLoader());
2659 boolean doRebind = s.onUnbind(data.intent);
2660 try {
2661 if (doRebind) {
2662 ActivityManagerNative.getDefault().unbindFinished(
2663 data.token, data.intent, doRebind);
2664 } else {
2665 ActivityManagerNative.getDefault().serviceDoneExecuting(
2666 data.token);
2667 }
2668 } catch (RemoteException ex) {
2669 }
2670 } catch (Exception e) {
2671 if (!mInstrumentation.onException(s, e)) {
2672 throw new RuntimeException(
2673 "Unable to unbind to service " + s
2674 + " with " + data.intent + ": " + e.toString(), e);
2675 }
2676 }
2677 }
2678 }
2679
2680 private void handleDumpService(DumpServiceInfo info) {
2681 try {
2682 Service s = mServices.get(info.service);
2683 if (s != null) {
2684 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
2685 s.dump(info.fd, pw, info.args);
2686 pw.close();
2687 }
2688 } finally {
2689 synchronized (info) {
2690 info.dumped = true;
2691 info.notifyAll();
2692 }
2693 }
2694 }
2695
2696 private final void handleServiceArgs(ServiceArgsData data) {
2697 Service s = mServices.get(data.token);
2698 if (s != null) {
2699 try {
2700 if (data.args != null) {
2701 data.args.setExtrasClassLoader(s.getClassLoader());
2702 }
2703 s.onStart(data.args, data.startId);
2704 try {
2705 ActivityManagerNative.getDefault().serviceDoneExecuting(data.token);
2706 } catch (RemoteException e) {
2707 // nothing to do.
2708 }
2709 } catch (Exception e) {
2710 if (!mInstrumentation.onException(s, e)) {
2711 throw new RuntimeException(
2712 "Unable to start service " + s
2713 + " with " + data.args + ": " + e.toString(), e);
2714 }
2715 }
2716 }
2717 }
2718
2719 private final void handleStopService(IBinder token) {
2720 Service s = mServices.remove(token);
2721 if (s != null) {
2722 try {
2723 if (localLOGV) Log.v(TAG, "Destroying service " + s);
2724 s.onDestroy();
2725 Context context = s.getBaseContext();
2726 if (context instanceof ApplicationContext) {
2727 final String who = s.getClassName();
2728 ((ApplicationContext) context).scheduleFinalCleanup(who, "Service");
2729 }
2730 try {
2731 ActivityManagerNative.getDefault().serviceDoneExecuting(token);
2732 } catch (RemoteException e) {
2733 // nothing to do.
2734 }
2735 } catch (Exception e) {
2736 if (!mInstrumentation.onException(s, e)) {
2737 throw new RuntimeException(
2738 "Unable to stop service " + s
2739 + ": " + e.toString(), e);
2740 }
2741 }
2742 }
2743 //Log.i(TAG, "Running services: " + mServices);
2744 }
2745
2746 public final ActivityRecord performResumeActivity(IBinder token,
2747 boolean clearHide) {
2748 ActivityRecord r = mActivities.get(token);
2749 if (localLOGV) Log.v(TAG, "Performing resume of " + r
2750 + " finished=" + r.activity.mFinished);
2751 if (r != null && !r.activity.mFinished) {
2752 if (clearHide) {
2753 r.hideForNow = false;
2754 r.activity.mStartedActivity = false;
2755 }
2756 try {
2757 if (r.pendingIntents != null) {
2758 deliverNewIntents(r, r.pendingIntents);
2759 r.pendingIntents = null;
2760 }
2761 if (r.pendingResults != null) {
2762 deliverResults(r, r.pendingResults);
2763 r.pendingResults = null;
2764 }
2765 r.activity.performResume();
2766
2767 EventLog.writeEvent(LOG_ON_RESUME_CALLED,
2768 r.activity.getComponentName().getClassName());
2769
2770 r.paused = false;
2771 r.stopped = false;
2772 if (r.activity.mStartedActivity) {
2773 r.hideForNow = true;
2774 }
2775 r.state = null;
2776 } catch (Exception e) {
2777 if (!mInstrumentation.onException(r.activity, e)) {
2778 throw new RuntimeException(
2779 "Unable to resume activity "
2780 + r.intent.getComponent().toShortString()
2781 + ": " + e.toString(), e);
2782 }
2783 }
2784 }
2785 return r;
2786 }
2787
2788 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
2789 // If we are getting ready to gc after going to the background, well
2790 // we are back active so skip it.
2791 unscheduleGcIdler();
2792
2793 ActivityRecord r = performResumeActivity(token, clearHide);
2794
2795 if (r != null) {
2796 final Activity a = r.activity;
2797
2798 if (localLOGV) Log.v(
2799 TAG, "Resume " + r + " started activity: " +
2800 a.mStartedActivity + ", hideForNow: " + r.hideForNow
2801 + ", finished: " + a.mFinished);
2802
2803 final int forwardBit = isForward ?
2804 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
2805
2806 // If the window hasn't yet been added to the window manager,
2807 // and this guy didn't finish itself or start another activity,
2808 // then go ahead and add the window.
2809 if (r.window == null && !a.mFinished && !a.mStartedActivity) {
2810 r.window = r.activity.getWindow();
2811 View decor = r.window.getDecorView();
2812 decor.setVisibility(View.INVISIBLE);
2813 ViewManager wm = a.getWindowManager();
2814 WindowManager.LayoutParams l = r.window.getAttributes();
2815 a.mDecor = decor;
2816 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2817 l.softInputMode |= forwardBit;
2818 if (a.mVisibleFromClient) {
2819 a.mWindowAdded = true;
2820 wm.addView(decor, l);
2821 }
2822
2823 // If the window has already been added, but during resume
2824 // we started another activity, then don't yet make the
2825 // window visisble.
2826 } else if (a.mStartedActivity) {
2827 if (localLOGV) Log.v(
2828 TAG, "Launch " + r + " mStartedActivity set");
2829 r.hideForNow = true;
2830 }
2831
2832 // The window is now visible if it has been added, we are not
2833 // simply finishing, and we are not starting another activity.
2834 if (!r.activity.mFinished && r.activity.mDecor != null
2835 && !r.hideForNow) {
2836 if (r.newConfig != null) {
2837 performConfigurationChanged(r.activity, r.newConfig);
2838 r.newConfig = null;
2839 }
2840 if (localLOGV) Log.v(TAG, "Resuming " + r + " with isForward="
2841 + isForward);
2842 WindowManager.LayoutParams l = r.window.getAttributes();
2843 if ((l.softInputMode
2844 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
2845 != forwardBit) {
2846 l.softInputMode = (l.softInputMode
2847 & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
2848 | forwardBit;
2849 ViewManager wm = a.getWindowManager();
2850 View decor = r.window.getDecorView();
2851 wm.updateViewLayout(decor, l);
2852 }
2853 r.activity.mVisibleFromServer = true;
2854 mNumVisibleActivities++;
2855 if (r.activity.mVisibleFromClient) {
2856 r.activity.makeVisible();
2857 }
2858 }
2859
2860 r.nextIdle = mNewActivities;
2861 mNewActivities = r;
2862 if (localLOGV) Log.v(
2863 TAG, "Scheduling idle handler for " + r);
2864 Looper.myQueue().addIdleHandler(new Idler());
2865
2866 } else {
2867 // If an exception was thrown when trying to resume, then
2868 // just end this activity.
2869 try {
2870 ActivityManagerNative.getDefault()
2871 .finishActivity(token, Activity.RESULT_CANCELED, null);
2872 } catch (RemoteException ex) {
2873 }
2874 }
2875 }
2876
2877 private int mThumbnailWidth = -1;
2878 private int mThumbnailHeight = -1;
2879
2880 private final Bitmap createThumbnailBitmap(ActivityRecord r) {
2881 Bitmap thumbnail = null;
2882 try {
2883 int w = mThumbnailWidth;
2884 int h;
2885 if (w < 0) {
2886 Resources res = r.activity.getResources();
2887 mThumbnailHeight = h =
2888 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
2889
2890 mThumbnailWidth = w =
2891 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
2892 } else {
2893 h = mThumbnailHeight;
2894 }
2895
2896 // XXX Only set hasAlpha if needed?
2897 thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
2898 thumbnail.eraseColor(0);
2899 Canvas cv = new Canvas(thumbnail);
2900 if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
2901 thumbnail = null;
2902 }
2903 } catch (Exception e) {
2904 if (!mInstrumentation.onException(r.activity, e)) {
2905 throw new RuntimeException(
2906 "Unable to create thumbnail of "
2907 + r.intent.getComponent().toShortString()
2908 + ": " + e.toString(), e);
2909 }
2910 thumbnail = null;
2911 }
2912
2913 return thumbnail;
2914 }
2915
2916 private final void handlePauseActivity(IBinder token, boolean finished,
2917 boolean userLeaving, int configChanges) {
2918 ActivityRecord r = mActivities.get(token);
2919 if (r != null) {
2920 //Log.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
2921 if (userLeaving) {
2922 performUserLeavingActivity(r);
2923 }
2924
2925 r.activity.mConfigChangeFlags |= configChanges;
2926 Bundle state = performPauseActivity(token, finished, true);
2927
2928 // Tell the activity manager we have paused.
2929 try {
2930 ActivityManagerNative.getDefault().activityPaused(token, state);
2931 } catch (RemoteException ex) {
2932 }
2933 }
2934 }
2935
2936 final void performUserLeavingActivity(ActivityRecord r) {
2937 mInstrumentation.callActivityOnUserLeaving(r.activity);
2938 }
2939
2940 final Bundle performPauseActivity(IBinder token, boolean finished,
2941 boolean saveState) {
2942 ActivityRecord r = mActivities.get(token);
2943 return r != null ? performPauseActivity(r, finished, saveState) : null;
2944 }
2945
2946 final Bundle performPauseActivity(ActivityRecord r, boolean finished,
2947 boolean saveState) {
2948 if (r.paused) {
2949 if (r.activity.mFinished) {
2950 // If we are finishing, we won't call onResume() in certain cases.
2951 // So here we likewise don't want to call onPause() if the activity
2952 // isn't resumed.
2953 return null;
2954 }
2955 RuntimeException e = new RuntimeException(
2956 "Performing pause of activity that is not resumed: "
2957 + r.intent.getComponent().toShortString());
2958 Log.e(TAG, e.getMessage(), e);
2959 }
2960 Bundle state = null;
2961 if (finished) {
2962 r.activity.mFinished = true;
2963 }
2964 try {
2965 // Next have the activity save its current state and managed dialogs...
2966 if (!r.activity.mFinished && saveState) {
2967 state = new Bundle();
2968 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
2969 r.state = state;
2970 }
2971 // Now we are idle.
2972 r.activity.mCalled = false;
2973 mInstrumentation.callActivityOnPause(r.activity);
2974 EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
2975 if (!r.activity.mCalled) {
2976 throw new SuperNotCalledException(
2977 "Activity " + r.intent.getComponent().toShortString() +
2978 " did not call through to super.onPause()");
2979 }
2980
2981 } catch (SuperNotCalledException e) {
2982 throw e;
2983
2984 } catch (Exception e) {
2985 if (!mInstrumentation.onException(r.activity, e)) {
2986 throw new RuntimeException(
2987 "Unable to pause activity "
2988 + r.intent.getComponent().toShortString()
2989 + ": " + e.toString(), e);
2990 }
2991 }
2992 r.paused = true;
2993 return state;
2994 }
2995
2996 final void performStopActivity(IBinder token) {
2997 ActivityRecord r = mActivities.get(token);
2998 performStopActivityInner(r, null, false);
2999 }
3000
3001 private static class StopInfo {
3002 Bitmap thumbnail;
3003 CharSequence description;
3004 }
3005
3006 private final class ProviderRefCount {
3007 public int count;
3008 ProviderRefCount(int pCount) {
3009 count = pCount;
3010 }
3011 }
3012
3013 private final void performStopActivityInner(ActivityRecord r,
3014 StopInfo info, boolean keepShown) {
3015 if (localLOGV) Log.v(TAG, "Performing stop of " + r);
3016 if (r != null) {
3017 if (!keepShown && r.stopped) {
3018 if (r.activity.mFinished) {
3019 // If we are finishing, we won't call onResume() in certain
3020 // cases. So here we likewise don't want to call onStop()
3021 // if the activity isn't resumed.
3022 return;
3023 }
3024 RuntimeException e = new RuntimeException(
3025 "Performing stop of activity that is not resumed: "
3026 + r.intent.getComponent().toShortString());
3027 Log.e(TAG, e.getMessage(), e);
3028 }
3029
3030 if (info != null) {
3031 try {
3032 // First create a thumbnail for the activity...
3033 //info.thumbnail = createThumbnailBitmap(r);
3034 info.description = r.activity.onCreateDescription();
3035 } catch (Exception e) {
3036 if (!mInstrumentation.onException(r.activity, e)) {
3037 throw new RuntimeException(
3038 "Unable to save state of activity "
3039 + r.intent.getComponent().toShortString()
3040 + ": " + e.toString(), e);
3041 }
3042 }
3043 }
3044
3045 if (!keepShown) {
3046 try {
3047 // Now we are idle.
3048 r.activity.performStop();
3049 } catch (Exception e) {
3050 if (!mInstrumentation.onException(r.activity, e)) {
3051 throw new RuntimeException(
3052 "Unable to stop activity "
3053 + r.intent.getComponent().toShortString()
3054 + ": " + e.toString(), e);
3055 }
3056 }
3057 r.stopped = true;
3058 }
3059
3060 r.paused = true;
3061 }
3062 }
3063
3064 private final void updateVisibility(ActivityRecord r, boolean show) {
3065 View v = r.activity.mDecor;
3066 if (v != null) {
3067 if (show) {
3068 if (!r.activity.mVisibleFromServer) {
3069 r.activity.mVisibleFromServer = true;
3070 mNumVisibleActivities++;
3071 if (r.activity.mVisibleFromClient) {
3072 r.activity.makeVisible();
3073 }
3074 }
3075 if (r.newConfig != null) {
3076 performConfigurationChanged(r.activity, r.newConfig);
3077 r.newConfig = null;
3078 }
3079 } else {
3080 if (r.activity.mVisibleFromServer) {
3081 r.activity.mVisibleFromServer = false;
3082 mNumVisibleActivities--;
3083 v.setVisibility(View.INVISIBLE);
3084 }
3085 }
3086 }
3087 }
3088
3089 private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
3090 ActivityRecord r = mActivities.get(token);
3091 r.activity.mConfigChangeFlags |= configChanges;
3092
3093 StopInfo info = new StopInfo();
3094 performStopActivityInner(r, info, show);
3095
3096 if (localLOGV) Log.v(
3097 TAG, "Finishing stop of " + r + ": show=" + show
3098 + " win=" + r.window);
3099
3100 updateVisibility(r, show);
3101
3102 // Tell activity manager we have been stopped.
3103 try {
3104 ActivityManagerNative.getDefault().activityStopped(
3105 r.token, info.thumbnail, info.description);
3106 } catch (RemoteException ex) {
3107 }
3108 }
3109
3110 final void performRestartActivity(IBinder token) {
3111 ActivityRecord r = mActivities.get(token);
3112 if (r.stopped) {
3113 r.activity.performRestart();
3114 r.stopped = false;
3115 }
3116 }
3117
3118 private final void handleWindowVisibility(IBinder token, boolean show) {
3119 ActivityRecord r = mActivities.get(token);
3120 if (!show && !r.stopped) {
3121 performStopActivityInner(r, null, show);
3122 } else if (show && r.stopped) {
3123 // If we are getting ready to gc after going to the background, well
3124 // we are back active so skip it.
3125 unscheduleGcIdler();
3126
3127 r.activity.performRestart();
3128 r.stopped = false;
3129 }
3130 if (r.activity.mDecor != null) {
3131 if (Config.LOGV) Log.v(
3132 TAG, "Handle window " + r + " visibility: " + show);
3133 updateVisibility(r, show);
3134 }
3135 }
3136
3137 private final void deliverResults(ActivityRecord r, List<ResultInfo> results) {
3138 final int N = results.size();
3139 for (int i=0; i<N; i++) {
3140 ResultInfo ri = results.get(i);
3141 try {
3142 if (ri.mData != null) {
3143 ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3144 }
Chris Tate8a7dc172009-03-24 20:11:42 -07003145 if (DEBUG_RESULTS) Log.v(TAG,
3146 "Delivering result to activity " + r + " : " + ri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003147 r.activity.dispatchActivityResult(ri.mResultWho,
3148 ri.mRequestCode, ri.mResultCode, ri.mData);
3149 } catch (Exception e) {
3150 if (!mInstrumentation.onException(r.activity, e)) {
3151 throw new RuntimeException(
3152 "Failure delivering result " + ri + " to activity "
3153 + r.intent.getComponent().toShortString()
3154 + ": " + e.toString(), e);
3155 }
3156 }
3157 }
3158 }
3159
3160 private final void handleSendResult(ResultData res) {
3161 ActivityRecord r = mActivities.get(res.token);
Chris Tate8a7dc172009-03-24 20:11:42 -07003162 if (DEBUG_RESULTS) Log.v(TAG, "Handling send result to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 if (r != null) {
3164 final boolean resumed = !r.paused;
3165 if (!r.activity.mFinished && r.activity.mDecor != null
3166 && r.hideForNow && resumed) {
3167 // We had hidden the activity because it started another
3168 // one... we have gotten a result back and we are not
3169 // paused, so make sure our window is visible.
3170 updateVisibility(r, true);
3171 }
3172 if (resumed) {
3173 try {
3174 // Now we are idle.
3175 r.activity.mCalled = false;
3176 mInstrumentation.callActivityOnPause(r.activity);
3177 if (!r.activity.mCalled) {
3178 throw new SuperNotCalledException(
3179 "Activity " + r.intent.getComponent().toShortString()
3180 + " did not call through to super.onPause()");
3181 }
3182 } catch (SuperNotCalledException e) {
3183 throw e;
3184 } catch (Exception e) {
3185 if (!mInstrumentation.onException(r.activity, e)) {
3186 throw new RuntimeException(
3187 "Unable to pause activity "
3188 + r.intent.getComponent().toShortString()
3189 + ": " + e.toString(), e);
3190 }
3191 }
3192 }
3193 deliverResults(r, res.results);
3194 if (resumed) {
3195 mInstrumentation.callActivityOnResume(r.activity);
3196 }
3197 }
3198 }
3199
3200 public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) {
3201 return performDestroyActivity(token, finishing, 0, false);
3202 }
3203
3204 private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing,
3205 int configChanges, boolean getNonConfigInstance) {
3206 ActivityRecord r = mActivities.get(token);
3207 if (localLOGV) Log.v(TAG, "Performing finish of " + r);
3208 if (r != null) {
3209 r.activity.mConfigChangeFlags |= configChanges;
3210 if (finishing) {
3211 r.activity.mFinished = true;
3212 }
3213 if (!r.paused) {
3214 try {
3215 r.activity.mCalled = false;
3216 mInstrumentation.callActivityOnPause(r.activity);
3217 EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
3218 r.activity.getComponentName().getClassName());
3219 if (!r.activity.mCalled) {
3220 throw new SuperNotCalledException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003221 "Activity " + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 + " did not call through to super.onPause()");
3223 }
3224 } catch (SuperNotCalledException e) {
3225 throw e;
3226 } catch (Exception e) {
3227 if (!mInstrumentation.onException(r.activity, e)) {
3228 throw new RuntimeException(
3229 "Unable to pause activity "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003230 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231 + ": " + e.toString(), e);
3232 }
3233 }
3234 r.paused = true;
3235 }
3236 if (!r.stopped) {
3237 try {
3238 r.activity.performStop();
3239 } catch (SuperNotCalledException e) {
3240 throw e;
3241 } catch (Exception e) {
3242 if (!mInstrumentation.onException(r.activity, e)) {
3243 throw new RuntimeException(
3244 "Unable to stop activity "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003245 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003246 + ": " + e.toString(), e);
3247 }
3248 }
3249 r.stopped = true;
3250 }
3251 if (getNonConfigInstance) {
3252 try {
3253 r.lastNonConfigurationInstance
3254 = r.activity.onRetainNonConfigurationInstance();
3255 } catch (Exception e) {
3256 if (!mInstrumentation.onException(r.activity, e)) {
3257 throw new RuntimeException(
3258 "Unable to retain activity "
3259 + r.intent.getComponent().toShortString()
3260 + ": " + e.toString(), e);
3261 }
3262 }
3263 try {
3264 r.lastNonConfigurationChildInstances
3265 = r.activity.onRetainNonConfigurationChildInstances();
3266 } catch (Exception e) {
3267 if (!mInstrumentation.onException(r.activity, e)) {
3268 throw new RuntimeException(
3269 "Unable to retain child activities "
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003270 + safeToComponentShortString(r.intent)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003271 + ": " + e.toString(), e);
3272 }
3273 }
3274
3275 }
3276 try {
3277 r.activity.mCalled = false;
3278 r.activity.onDestroy();
3279 if (!r.activity.mCalled) {
3280 throw new SuperNotCalledException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003281 "Activity " + safeToComponentShortString(r.intent) +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 " did not call through to super.onDestroy()");
3283 }
3284 if (r.window != null) {
3285 r.window.closeAllPanels();
3286 }
3287 } catch (SuperNotCalledException e) {
3288 throw e;
3289 } catch (Exception e) {
3290 if (!mInstrumentation.onException(r.activity, e)) {
3291 throw new RuntimeException(
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003292 "Unable to destroy activity " + safeToComponentShortString(r.intent)
3293 + ": " + e.toString(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 }
3295 }
3296 }
3297 mActivities.remove(token);
3298
3299 return r;
3300 }
3301
Mitsuru Oshimad9aef732009-06-16 20:20:50 -07003302 private static String safeToComponentShortString(Intent intent) {
3303 ComponentName component = intent.getComponent();
3304 return component == null ? "[Unknown]" : component.toShortString();
3305 }
3306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003307 private final void handleDestroyActivity(IBinder token, boolean finishing,
3308 int configChanges, boolean getNonConfigInstance) {
3309 ActivityRecord r = performDestroyActivity(token, finishing,
3310 configChanges, getNonConfigInstance);
3311 if (r != null) {
3312 WindowManager wm = r.activity.getWindowManager();
3313 View v = r.activity.mDecor;
3314 if (v != null) {
3315 if (r.activity.mVisibleFromServer) {
3316 mNumVisibleActivities--;
3317 }
3318 IBinder wtoken = v.getWindowToken();
3319 if (r.activity.mWindowAdded) {
3320 wm.removeViewImmediate(v);
3321 }
3322 if (wtoken != null) {
3323 WindowManagerImpl.getDefault().closeAll(wtoken,
3324 r.activity.getClass().getName(), "Activity");
3325 }
3326 r.activity.mDecor = null;
3327 }
3328 WindowManagerImpl.getDefault().closeAll(token,
3329 r.activity.getClass().getName(), "Activity");
3330
3331 // Mocked out contexts won't be participating in the normal
3332 // process lifecycle, but if we're running with a proper
3333 // ApplicationContext we need to have it tear down things
3334 // cleanly.
3335 Context c = r.activity.getBaseContext();
3336 if (c instanceof ApplicationContext) {
3337 ((ApplicationContext) c).scheduleFinalCleanup(
3338 r.activity.getClass().getName(), "Activity");
3339 }
3340 }
3341 if (finishing) {
3342 try {
3343 ActivityManagerNative.getDefault().activityDestroyed(token);
3344 } catch (RemoteException ex) {
3345 // If the system process has died, it's game over for everyone.
3346 }
3347 }
3348 }
3349
3350 private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) {
3351 // If we are getting ready to gc after going to the background, well
3352 // we are back active so skip it.
3353 unscheduleGcIdler();
3354
3355 Configuration changedConfig = null;
3356
3357 // First: make sure we have the most recent configuration and most
3358 // recent version of the activity, or skip it if some previous call
3359 // had taken a more recent version.
3360 synchronized (mRelaunchingActivities) {
3361 int N = mRelaunchingActivities.size();
3362 IBinder token = tmp.token;
3363 tmp = null;
3364 for (int i=0; i<N; i++) {
3365 ActivityRecord r = mRelaunchingActivities.get(i);
3366 if (r.token == token) {
3367 tmp = r;
3368 mRelaunchingActivities.remove(i);
3369 i--;
3370 N--;
3371 }
3372 }
3373
3374 if (tmp == null) {
3375 return;
3376 }
3377
3378 if (mPendingConfiguration != null) {
3379 changedConfig = mPendingConfiguration;
3380 mPendingConfiguration = null;
3381 }
3382 }
3383
3384 // If there was a pending configuration change, execute it first.
3385 if (changedConfig != null) {
3386 handleConfigurationChanged(changedConfig);
3387 }
3388
3389 ActivityRecord r = mActivities.get(tmp.token);
3390 if (localLOGV) Log.v(TAG, "Handling relaunch of " + r);
3391 if (r == null) {
3392 return;
3393 }
3394
3395 r.activity.mConfigChangeFlags |= configChanges;
Christopher Tateb70f3df2009-04-07 16:07:59 -07003396 Intent currentIntent = r.activity.mIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397
3398 Bundle savedState = null;
3399 if (!r.paused) {
3400 savedState = performPauseActivity(r.token, false, true);
3401 }
3402
3403 handleDestroyActivity(r.token, false, configChanges, true);
3404
3405 r.activity = null;
3406 r.window = null;
3407 r.hideForNow = false;
3408 r.nextIdle = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07003409 // Merge any pending results and pending intents; don't just replace them
3410 if (tmp.pendingResults != null) {
3411 if (r.pendingResults == null) {
3412 r.pendingResults = tmp.pendingResults;
3413 } else {
3414 r.pendingResults.addAll(tmp.pendingResults);
3415 }
3416 }
3417 if (tmp.pendingIntents != null) {
3418 if (r.pendingIntents == null) {
3419 r.pendingIntents = tmp.pendingIntents;
3420 } else {
3421 r.pendingIntents.addAll(tmp.pendingIntents);
3422 }
3423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 r.startsNotResumed = tmp.startsNotResumed;
3425 if (savedState != null) {
3426 r.state = savedState;
3427 }
3428
Christopher Tateb70f3df2009-04-07 16:07:59 -07003429 handleLaunchActivity(r, currentIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 }
3431
3432 private final void handleRequestThumbnail(IBinder token) {
3433 ActivityRecord r = mActivities.get(token);
3434 Bitmap thumbnail = createThumbnailBitmap(r);
3435 CharSequence description = null;
3436 try {
3437 description = r.activity.onCreateDescription();
3438 } catch (Exception e) {
3439 if (!mInstrumentation.onException(r.activity, e)) {
3440 throw new RuntimeException(
3441 "Unable to create description of activity "
3442 + r.intent.getComponent().toShortString()
3443 + ": " + e.toString(), e);
3444 }
3445 }
3446 //System.out.println("Reporting top thumbnail " + thumbnail);
3447 try {
3448 ActivityManagerNative.getDefault().reportThumbnail(
3449 token, thumbnail, description);
3450 } catch (RemoteException ex) {
3451 }
3452 }
3453
3454 ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
3455 boolean allActivities, Configuration newConfig) {
3456 ArrayList<ComponentCallbacks> callbacks
3457 = new ArrayList<ComponentCallbacks>();
3458
3459 if (mActivities.size() > 0) {
3460 Iterator<ActivityRecord> it = mActivities.values().iterator();
3461 while (it.hasNext()) {
3462 ActivityRecord ar = it.next();
3463 Activity a = ar.activity;
3464 if (a != null) {
3465 if (!ar.activity.mFinished && (allActivities ||
3466 (a != null && !ar.paused))) {
3467 // If the activity is currently resumed, its configuration
3468 // needs to change right now.
3469 callbacks.add(a);
3470 } else if (newConfig != null) {
3471 // Otherwise, we will tell it about the change
3472 // the next time it is resumed or shown. Note that
3473 // the activity manager may, before then, decide the
3474 // activity needs to be destroyed to handle its new
3475 // configuration.
3476 ar.newConfig = newConfig;
3477 }
3478 }
3479 }
3480 }
3481 if (mServices.size() > 0) {
3482 Iterator<Service> it = mServices.values().iterator();
3483 while (it.hasNext()) {
3484 callbacks.add(it.next());
3485 }
3486 }
3487 synchronized (mProviderMap) {
3488 if (mLocalProviders.size() > 0) {
3489 Iterator<ProviderRecord> it = mLocalProviders.values().iterator();
3490 while (it.hasNext()) {
3491 callbacks.add(it.next().mLocalProvider);
3492 }
3493 }
3494 }
3495 final int N = mAllApplications.size();
3496 for (int i=0; i<N; i++) {
3497 callbacks.add(mAllApplications.get(i));
3498 }
3499
3500 return callbacks;
3501 }
3502
3503 private final void performConfigurationChanged(
3504 ComponentCallbacks cb, Configuration config) {
3505 // Only for Activity objects, check that they actually call up to their
3506 // superclass implementation. ComponentCallbacks is an interface, so
3507 // we check the runtime type and act accordingly.
3508 Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
3509 if (activity != null) {
3510 activity.mCalled = false;
3511 }
3512
3513 boolean shouldChangeConfig = false;
3514 if ((activity == null) || (activity.mCurrentConfig == null)) {
3515 shouldChangeConfig = true;
3516 } else {
3517
3518 // If the new config is the same as the config this Activity
3519 // is already running with then don't bother calling
3520 // onConfigurationChanged
3521 int diff = activity.mCurrentConfig.diff(config);
3522 if (diff != 0) {
3523
3524 // If this activity doesn't handle any of the config changes
3525 // then don't bother calling onConfigurationChanged as we're
3526 // going to destroy it.
3527 if ((~activity.mActivityInfo.configChanges & diff) == 0) {
3528 shouldChangeConfig = true;
3529 }
3530 }
3531 }
3532
3533 if (shouldChangeConfig) {
3534 cb.onConfigurationChanged(config);
3535
3536 if (activity != null) {
3537 if (!activity.mCalled) {
3538 throw new SuperNotCalledException(
3539 "Activity " + activity.getLocalClassName() +
3540 " did not call through to super.onConfigurationChanged()");
3541 }
3542 activity.mConfigChangeFlags = 0;
3543 activity.mCurrentConfig = new Configuration(config);
3544 }
3545 }
3546 }
3547
3548 final void handleConfigurationChanged(Configuration config) {
3549
3550 synchronized (mRelaunchingActivities) {
3551 if (mPendingConfiguration != null) {
3552 config = mPendingConfiguration;
3553 mPendingConfiguration = null;
3554 }
3555 }
3556
3557 ArrayList<ComponentCallbacks> callbacks
3558 = new ArrayList<ComponentCallbacks>();
3559
3560 synchronized(mPackages) {
3561 if (mConfiguration == null) {
3562 mConfiguration = new Configuration();
3563 }
3564 mConfiguration.updateFrom(config);
3565 DisplayMetrics dm = getDisplayMetricsLocked(true);
3566
3567 // set it for java, this also affects newly created Resources
3568 if (config.locale != null) {
3569 Locale.setDefault(config.locale);
3570 }
3571
3572 Resources.updateSystemConfiguration(config, null);
3573
3574 ApplicationContext.ApplicationPackageManager.configurationChanged();
3575 //Log.i(TAG, "Configuration changed in " + currentPackageName());
3576 {
3577 Iterator<WeakReference<Resources>> it =
3578 mActiveResources.values().iterator();
3579 //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
3580 // mActiveResources.entrySet().iterator();
3581 while (it.hasNext()) {
3582 WeakReference<Resources> v = it.next();
3583 Resources r = v.get();
3584 if (r != null) {
Mitsuru Oshima9189cab2009-06-03 11:19:12 -07003585 r.updateConfiguration(config, dm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 //Log.i(TAG, "Updated app resources " + v.getKey()
3587 // + " " + r + ": " + r.getConfiguration());
3588 } else {
3589 //Log.i(TAG, "Removing old resources " + v.getKey());
3590 it.remove();
3591 }
3592 }
3593 }
3594
3595 callbacks = collectComponentCallbacksLocked(false, config);
3596 }
3597
3598 final int N = callbacks.size();
3599 for (int i=0; i<N; i++) {
3600 performConfigurationChanged(callbacks.get(i), config);
3601 }
3602 }
3603
3604 final void handleActivityConfigurationChanged(IBinder token) {
3605 ActivityRecord r = mActivities.get(token);
3606 if (r == null || r.activity == null) {
3607 return;
3608 }
3609
3610 performConfigurationChanged(r.activity, mConfiguration);
3611 }
3612
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -08003613 final void handleProfilerControl(boolean start, String path) {
3614 if (start) {
3615 File file = new File(path);
3616 file.getParentFile().mkdirs();
3617 try {
3618 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
3619 } catch (RuntimeException e) {
3620 Log.w(TAG, "Profiling failed on path " + path
3621 + " -- can the process access this path?");
3622 }
3623 } else {
3624 Debug.stopMethodTracing();
3625 }
3626 }
3627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 final void handleLowMemory() {
3629 ArrayList<ComponentCallbacks> callbacks
3630 = new ArrayList<ComponentCallbacks>();
3631
3632 synchronized(mPackages) {
3633 callbacks = collectComponentCallbacksLocked(true, null);
3634 }
3635
3636 final int N = callbacks.size();
3637 for (int i=0; i<N; i++) {
3638 callbacks.get(i).onLowMemory();
3639 }
3640
Chris Tatece229052009-03-25 16:44:52 -07003641 // Ask SQLite to free up as much memory as it can, mostly from its page caches.
3642 if (Process.myUid() != Process.SYSTEM_UID) {
3643 int sqliteReleased = SQLiteDatabase.releaseMemory();
3644 EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
3645 }
Mike Reedcaf0df12009-04-27 14:32:05 -04003646
3647 // Ask graphics to free up as much as possible (font/image caches)
3648 Canvas.freeCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003649
3650 BinderInternal.forceGc("mem");
3651 }
3652
3653 private final void handleBindApplication(AppBindData data) {
3654 mBoundApplication = data;
3655 mConfiguration = new Configuration(data.config);
3656
3657 // We now rely on this being set by zygote.
3658 //Process.setGid(data.appInfo.gid);
3659 //Process.setUid(data.appInfo.uid);
3660
3661 // send up app name; do this *before* waiting for debugger
3662 android.ddm.DdmHandleAppName.setAppName(data.processName);
3663
3664 /*
3665 * Before spawning a new process, reset the time zone to be the system time zone.
3666 * This needs to be done because the system time zone could have changed after the
3667 * the spawning of this process. Without doing this this process would have the incorrect
3668 * system time zone.
3669 */
3670 TimeZone.setDefault(null);
3671
3672 /*
3673 * Initialize the default locale in this process for the reasons we set the time zone.
3674 */
3675 Locale.setDefault(data.config.locale);
3676
3677 data.info = getPackageInfoNoCheck(data.appInfo);
3678
3679 if (data.debugMode != IApplicationThread.DEBUG_OFF) {
3680 // XXX should have option to change the port.
3681 Debug.changeDebugPort(8100);
3682 if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
3683 Log.w(TAG, "Application " + data.info.getPackageName()
3684 + " is waiting for the debugger on port 8100...");
3685
3686 IActivityManager mgr = ActivityManagerNative.getDefault();
3687 try {
3688 mgr.showWaitingForDebugger(mAppThread, true);
3689 } catch (RemoteException ex) {
3690 }
3691
3692 Debug.waitForDebugger();
3693
3694 try {
3695 mgr.showWaitingForDebugger(mAppThread, false);
3696 } catch (RemoteException ex) {
3697 }
3698
3699 } else {
3700 Log.w(TAG, "Application " + data.info.getPackageName()
3701 + " can be debugged on port 8100...");
3702 }
3703 }
3704
3705 if (data.instrumentationName != null) {
3706 ApplicationContext appContext = new ApplicationContext();
3707 appContext.init(data.info, null, this);
3708 InstrumentationInfo ii = null;
3709 try {
3710 ii = appContext.getPackageManager().
3711 getInstrumentationInfo(data.instrumentationName, 0);
3712 } catch (PackageManager.NameNotFoundException e) {
3713 }
3714 if (ii == null) {
3715 throw new RuntimeException(
3716 "Unable to find instrumentation info for: "
3717 + data.instrumentationName);
3718 }
3719
3720 mInstrumentationAppDir = ii.sourceDir;
3721 mInstrumentationAppPackage = ii.packageName;
3722 mInstrumentedAppDir = data.info.getAppDir();
3723
3724 ApplicationInfo instrApp = new ApplicationInfo();
3725 instrApp.packageName = ii.packageName;
3726 instrApp.sourceDir = ii.sourceDir;
3727 instrApp.publicSourceDir = ii.publicSourceDir;
3728 instrApp.dataDir = ii.dataDir;
3729 PackageInfo pi = getPackageInfo(instrApp,
3730 appContext.getClassLoader(), false, true);
3731 ApplicationContext instrContext = new ApplicationContext();
3732 instrContext.init(pi, null, this);
3733
3734 try {
3735 java.lang.ClassLoader cl = instrContext.getClassLoader();
3736 mInstrumentation = (Instrumentation)
3737 cl.loadClass(data.instrumentationName.getClassName()).newInstance();
3738 } catch (Exception e) {
3739 throw new RuntimeException(
3740 "Unable to instantiate instrumentation "
3741 + data.instrumentationName + ": " + e.toString(), e);
3742 }
3743
3744 mInstrumentation.init(this, instrContext, appContext,
3745 new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
3746
3747 if (data.profileFile != null && !ii.handleProfiling) {
3748 data.handlingProfiling = true;
3749 File file = new File(data.profileFile);
3750 file.getParentFile().mkdirs();
3751 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
3752 }
3753
3754 try {
3755 mInstrumentation.onCreate(data.instrumentationArgs);
3756 }
3757 catch (Exception e) {
3758 throw new RuntimeException(
3759 "Exception thrown in onCreate() of "
3760 + data.instrumentationName + ": " + e.toString(), e);
3761 }
3762
3763 } else {
3764 mInstrumentation = new Instrumentation();
3765 }
3766
Christopher Tate181fafa2009-05-14 11:12:14 -07003767 // If the app is being launched for full backup or restore, bring it up in
3768 // a restricted environment with the base application class.
3769 Application app = data.info.makeApplication(data.restrictedBackupMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003770 mInitialApplication = app;
3771
3772 List<ProviderInfo> providers = data.providers;
3773 if (providers != null) {
3774 installContentProviders(app, providers);
3775 }
3776
3777 try {
3778 mInstrumentation.callApplicationOnCreate(app);
3779 } catch (Exception e) {
3780 if (!mInstrumentation.onException(app, e)) {
3781 throw new RuntimeException(
3782 "Unable to create application " + app.getClass().getName()
3783 + ": " + e.toString(), e);
3784 }
3785 }
3786 }
3787
3788 /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
3789 IActivityManager am = ActivityManagerNative.getDefault();
3790 if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
3791 Debug.stopMethodTracing();
3792 }
3793 //Log.i(TAG, "am: " + ActivityManagerNative.getDefault()
3794 // + ", app thr: " + mAppThread);
3795 try {
3796 am.finishInstrumentation(mAppThread, resultCode, results);
3797 } catch (RemoteException ex) {
3798 }
3799 }
3800
3801 private final void installContentProviders(
3802 Context context, List<ProviderInfo> providers) {
3803 final ArrayList<IActivityManager.ContentProviderHolder> results =
3804 new ArrayList<IActivityManager.ContentProviderHolder>();
3805
3806 Iterator<ProviderInfo> i = providers.iterator();
3807 while (i.hasNext()) {
3808 ProviderInfo cpi = i.next();
3809 StringBuilder buf = new StringBuilder(128);
3810 buf.append("Publishing provider ");
3811 buf.append(cpi.authority);
3812 buf.append(": ");
3813 buf.append(cpi.name);
3814 Log.i(TAG, buf.toString());
3815 IContentProvider cp = installProvider(context, null, cpi, false);
3816 if (cp != null) {
3817 IActivityManager.ContentProviderHolder cph =
3818 new IActivityManager.ContentProviderHolder(cpi);
3819 cph.provider = cp;
3820 results.add(cph);
3821 // Don't ever unload this provider from the process.
3822 synchronized(mProviderMap) {
3823 mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
3824 }
3825 }
3826 }
3827
3828 try {
3829 ActivityManagerNative.getDefault().publishContentProviders(
3830 getApplicationThread(), results);
3831 } catch (RemoteException ex) {
3832 }
3833 }
3834
3835 private final IContentProvider getProvider(Context context, String name) {
3836 synchronized(mProviderMap) {
3837 final ProviderRecord pr = mProviderMap.get(name);
3838 if (pr != null) {
3839 return pr.mProvider;
3840 }
3841 }
3842
3843 IActivityManager.ContentProviderHolder holder = null;
3844 try {
3845 holder = ActivityManagerNative.getDefault().getContentProvider(
3846 getApplicationThread(), name);
3847 } catch (RemoteException ex) {
3848 }
3849 if (holder == null) {
3850 Log.e(TAG, "Failed to find provider info for " + name);
3851 return null;
3852 }
3853 if (holder.permissionFailure != null) {
3854 throw new SecurityException("Permission " + holder.permissionFailure
3855 + " required for provider " + name);
3856 }
3857
3858 IContentProvider prov = installProvider(context, holder.provider,
3859 holder.info, true);
3860 //Log.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
3861 if (holder.noReleaseNeeded || holder.provider == null) {
3862 // We are not going to release the provider if it is an external
3863 // provider that doesn't care about being released, or if it is
3864 // a local provider running in this process.
3865 //Log.i(TAG, "*** NO RELEASE NEEDED");
3866 synchronized(mProviderMap) {
3867 mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
3868 }
3869 }
3870 return prov;
3871 }
3872
3873 public final IContentProvider acquireProvider(Context c, String name) {
3874 IContentProvider provider = getProvider(c, name);
3875 if(provider == null)
3876 return null;
3877 IBinder jBinder = provider.asBinder();
3878 synchronized(mProviderMap) {
3879 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
3880 if(prc == null) {
3881 mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
3882 } else {
3883 prc.count++;
3884 } //end else
3885 } //end synchronized
3886 return provider;
3887 }
3888
3889 public final boolean releaseProvider(IContentProvider provider) {
3890 if(provider == null) {
3891 return false;
3892 }
3893 IBinder jBinder = provider.asBinder();
3894 synchronized(mProviderMap) {
3895 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
3896 if(prc == null) {
3897 if(localLOGV) Log.v(TAG, "releaseProvider::Weird shouldnt be here");
3898 return false;
3899 } else {
3900 prc.count--;
3901 if(prc.count == 0) {
3902 mProviderRefCountMap.remove(jBinder);
3903 //invoke removeProvider to dereference provider
3904 removeProviderLocked(provider);
3905 } //end if
3906 } //end else
3907 } //end synchronized
3908 return true;
3909 }
3910
3911 public final void removeProviderLocked(IContentProvider provider) {
3912 if (provider == null) {
3913 return;
3914 }
3915 IBinder providerBinder = provider.asBinder();
3916 boolean amRemoveFlag = false;
3917
3918 // remove the provider from mProviderMap
3919 Iterator<ProviderRecord> iter = mProviderMap.values().iterator();
3920 while (iter.hasNext()) {
3921 ProviderRecord pr = iter.next();
3922 IBinder myBinder = pr.mProvider.asBinder();
3923 if (myBinder == providerBinder) {
3924 //find if its published by this process itself
3925 if(pr.mLocalProvider != null) {
3926 if(localLOGV) Log.i(TAG, "removeProvider::found local provider returning");
3927 return;
3928 }
3929 if(localLOGV) Log.v(TAG, "removeProvider::Not local provider Unlinking " +
3930 "death recipient");
3931 //content provider is in another process
3932 myBinder.unlinkToDeath(pr, 0);
3933 iter.remove();
3934 //invoke remove only once for the very first name seen
3935 if(!amRemoveFlag) {
3936 try {
3937 if(localLOGV) Log.v(TAG, "removeProvider::Invoking " +
3938 "ActivityManagerNative.removeContentProvider("+pr.mName);
3939 ActivityManagerNative.getDefault().removeContentProvider(getApplicationThread(), pr.mName);
3940 amRemoveFlag = true;
3941 } catch (RemoteException e) {
3942 //do nothing content provider object is dead any way
3943 } //end catch
3944 }
3945 } //end if myBinder
3946 } //end while iter
3947 }
3948
3949 final void removeDeadProvider(String name, IContentProvider provider) {
3950 synchronized(mProviderMap) {
3951 ProviderRecord pr = mProviderMap.get(name);
3952 if (pr.mProvider.asBinder() == provider.asBinder()) {
3953 Log.i(TAG, "Removing dead content provider: " + name);
3954 mProviderMap.remove(name);
3955 }
3956 }
3957 }
3958
3959 final void removeDeadProviderLocked(String name, IContentProvider provider) {
3960 ProviderRecord pr = mProviderMap.get(name);
3961 if (pr.mProvider.asBinder() == provider.asBinder()) {
3962 Log.i(TAG, "Removing dead content provider: " + name);
3963 mProviderMap.remove(name);
3964 }
3965 }
3966
3967 private final IContentProvider installProvider(Context context,
3968 IContentProvider provider, ProviderInfo info, boolean noisy) {
3969 ContentProvider localProvider = null;
3970 if (provider == null) {
3971 if (noisy) {
3972 Log.d(TAG, "Loading provider " + info.authority + ": "
3973 + info.name);
3974 }
3975 Context c = null;
3976 ApplicationInfo ai = info.applicationInfo;
3977 if (context.getPackageName().equals(ai.packageName)) {
3978 c = context;
3979 } else if (mInitialApplication != null &&
3980 mInitialApplication.getPackageName().equals(ai.packageName)) {
3981 c = mInitialApplication;
3982 } else {
3983 try {
3984 c = context.createPackageContext(ai.packageName,
3985 Context.CONTEXT_INCLUDE_CODE);
3986 } catch (PackageManager.NameNotFoundException e) {
3987 }
3988 }
3989 if (c == null) {
3990 Log.w(TAG, "Unable to get context for package " +
3991 ai.packageName +
3992 " while loading content provider " +
3993 info.name);
3994 return null;
3995 }
3996 try {
3997 final java.lang.ClassLoader cl = c.getClassLoader();
3998 localProvider = (ContentProvider)cl.
3999 loadClass(info.name).newInstance();
4000 provider = localProvider.getIContentProvider();
4001 if (provider == null) {
4002 Log.e(TAG, "Failed to instantiate class " +
4003 info.name + " from sourceDir " +
4004 info.applicationInfo.sourceDir);
4005 return null;
4006 }
4007 if (Config.LOGV) Log.v(
4008 TAG, "Instantiating local provider " + info.name);
4009 // XXX Need to create the correct context for this provider.
4010 localProvider.attachInfo(c, info);
4011 } catch (java.lang.Exception e) {
4012 if (!mInstrumentation.onException(null, e)) {
4013 throw new RuntimeException(
4014 "Unable to get provider " + info.name
4015 + ": " + e.toString(), e);
4016 }
4017 return null;
4018 }
4019 } else if (localLOGV) {
4020 Log.v(TAG, "Installing external provider " + info.authority + ": "
4021 + info.name);
4022 }
4023
4024 synchronized (mProviderMap) {
4025 // Cache the pointer for the remote provider.
4026 String names[] = PATTERN_SEMICOLON.split(info.authority);
4027 for (int i=0; i<names.length; i++) {
4028 ProviderRecord pr = new ProviderRecord(names[i], provider,
4029 localProvider);
4030 try {
4031 provider.asBinder().linkToDeath(pr, 0);
4032 mProviderMap.put(names[i], pr);
4033 } catch (RemoteException e) {
4034 return null;
4035 }
4036 }
4037 if (localProvider != null) {
4038 mLocalProviders.put(provider.asBinder(),
4039 new ProviderRecord(null, provider, localProvider));
4040 }
4041 }
4042
4043 return provider;
4044 }
4045
4046 private final void attach(boolean system) {
4047 sThreadLocal.set(this);
4048 mSystemThread = system;
4049 AndroidHttpClient.setThreadBlocked(true);
4050 if (!system) {
4051 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
4052 RuntimeInit.setApplicationObject(mAppThread.asBinder());
4053 IActivityManager mgr = ActivityManagerNative.getDefault();
4054 try {
4055 mgr.attachApplication(mAppThread);
4056 } catch (RemoteException ex) {
4057 }
4058 } else {
4059 // Don't set application object here -- if the system crashes,
4060 // we can't display an alert, we just want to die die die.
4061 android.ddm.DdmHandleAppName.setAppName("system_process");
4062 try {
4063 mInstrumentation = new Instrumentation();
4064 ApplicationContext context = new ApplicationContext();
4065 context.init(getSystemContext().mPackageInfo, null, this);
4066 Application app = Instrumentation.newApplication(Application.class, context);
4067 mAllApplications.add(app);
4068 mInitialApplication = app;
4069 app.onCreate();
4070 } catch (Exception e) {
4071 throw new RuntimeException(
4072 "Unable to instantiate Application():" + e.toString(), e);
4073 }
4074 }
4075 }
4076
4077 private final void detach()
4078 {
4079 AndroidHttpClient.setThreadBlocked(false);
4080 sThreadLocal.set(null);
4081 }
4082
4083 public static final ActivityThread systemMain() {
4084 ActivityThread thread = new ActivityThread();
4085 thread.attach(true);
4086 return thread;
4087 }
4088
4089 public final void installSystemProviders(List providers) {
4090 if (providers != null) {
4091 installContentProviders(mInitialApplication,
4092 (List<ProviderInfo>)providers);
4093 }
4094 }
4095
4096 public static final void main(String[] args) {
4097 Process.setArgV0("<pre-initialized>");
4098
4099 Looper.prepareMainLooper();
4100
4101 ActivityThread thread = new ActivityThread();
4102 thread.attach(false);
4103
4104 Looper.loop();
4105
4106 if (Process.supportsProcesses()) {
4107 throw new RuntimeException("Main thread loop unexpectedly exited");
4108 }
4109
4110 thread.detach();
4111 String name;
4112 if (thread.mInitialApplication != null) name = thread.mInitialApplication.getPackageName();
4113 else name = "<unknown>";
4114 Log.i(TAG, "Main thread of " + name + " is now exiting");
4115 }
4116}