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