OSDN Git Service

Merge "add Toshiba usb driver link delete Fujitsu-Toshiba bug: 9755017" into jb-mr1...
[android-x86/frameworks-base.git] / core / java / android / app / ActivityThread.java
1 /*
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
17 package android.app;
18
19 import android.app.backup.BackupAgent;
20 import android.content.BroadcastReceiver;
21 import android.content.ComponentCallbacks2;
22 import android.content.ComponentName;
23 import android.content.ContentProvider;
24 import android.content.Context;
25 import android.content.IContentProvider;
26 import android.content.Intent;
27 import android.content.IIntentReceiver;
28 import android.content.pm.ActivityInfo;
29 import android.content.pm.ApplicationInfo;
30 import android.content.pm.IPackageManager;
31 import android.content.pm.InstrumentationInfo;
32 import android.content.pm.PackageInfo;
33 import android.content.pm.PackageManager;
34 import android.content.pm.PackageManager.NameNotFoundException;
35 import android.content.pm.ProviderInfo;
36 import android.content.pm.ServiceInfo;
37 import android.content.res.AssetManager;
38 import android.content.res.CompatibilityInfo;
39 import android.content.res.Configuration;
40 import android.content.res.Resources;
41 import android.database.sqlite.SQLiteDatabase;
42 import android.database.sqlite.SQLiteDebug;
43 import android.database.sqlite.SQLiteDebug.DbStats;
44 import android.graphics.Bitmap;
45 import android.graphics.Canvas;
46 import android.hardware.display.DisplayManager;
47 import android.hardware.display.DisplayManagerGlobal;
48 import android.net.IConnectivityManager;
49 import android.net.Proxy;
50 import android.net.ProxyProperties;
51 import android.opengl.GLUtils;
52 import android.os.AsyncTask;
53 import android.os.Binder;
54 import android.os.Bundle;
55 import android.os.Debug;
56 import android.os.DropBoxManager;
57 import android.os.Environment;
58 import android.os.Handler;
59 import android.os.IBinder;
60 import android.os.Looper;
61 import android.os.Message;
62 import android.os.MessageQueue;
63 import android.os.ParcelFileDescriptor;
64 import android.os.Process;
65 import android.os.RemoteException;
66 import android.os.ServiceManager;
67 import android.os.StrictMode;
68 import android.os.SystemClock;
69 import android.os.SystemProperties;
70 import android.os.Trace;
71 import android.os.UserHandle;
72 import android.util.AndroidRuntimeException;
73 import android.util.DisplayMetrics;
74 import android.util.EventLog;
75 import android.util.Log;
76 import android.util.LogPrinter;
77 import android.util.PrintWriterPrinter;
78 import android.util.Slog;
79 import android.view.CompatibilityInfoHolder;
80 import android.view.Display;
81 import android.view.HardwareRenderer;
82 import android.view.View;
83 import android.view.ViewDebug;
84 import android.view.ViewManager;
85 import android.view.ViewRootImpl;
86 import android.view.Window;
87 import android.view.WindowManager;
88 import android.view.WindowManagerGlobal;
89 import android.renderscript.RenderScript;
90
91 import com.android.internal.os.BinderInternal;
92 import com.android.internal.os.RuntimeInit;
93 import com.android.internal.os.SamplingProfilerIntegration;
94 import com.android.internal.util.Objects;
95
96 import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
97
98 import java.io.File;
99 import java.io.FileDescriptor;
100 import java.io.FileOutputStream;
101 import java.io.IOException;
102 import java.io.PrintWriter;
103 import java.lang.ref.WeakReference;
104 import java.net.InetAddress;
105 import java.security.Security;
106 import java.util.ArrayList;
107 import java.util.HashMap;
108 import java.util.Iterator;
109 import java.util.List;
110 import java.util.Locale;
111 import java.util.Map;
112 import java.util.TimeZone;
113 import java.util.regex.Pattern;
114
115 import libcore.io.DropBox;
116 import libcore.io.EventLogger;
117 import libcore.io.IoUtils;
118
119 import dalvik.system.CloseGuard;
120
121 final class SuperNotCalledException extends AndroidRuntimeException {
122     public SuperNotCalledException(String msg) {
123         super(msg);
124     }
125 }
126
127 final class RemoteServiceException extends AndroidRuntimeException {
128     public RemoteServiceException(String msg) {
129         super(msg);
130     }
131 }
132
133 /**
134  * This manages the execution of the main thread in an
135  * application process, scheduling and executing activities,
136  * broadcasts, and other operations on it as the activity
137  * manager requests.
138  *
139  * {@hide}
140  */
141 public final class ActivityThread {
142     /** @hide */
143     public static final String TAG = "ActivityThread";
144     private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
145     static final boolean localLOGV = false;
146     static final boolean DEBUG_MESSAGES = false;
147     /** @hide */
148     public static final boolean DEBUG_BROADCAST = false;
149     private static final boolean DEBUG_RESULTS = false;
150     private static final boolean DEBUG_BACKUP = false;
151     private static final boolean DEBUG_CONFIGURATION = false;
152     private static final boolean DEBUG_SERVICE = false;
153     private static final boolean DEBUG_MEMORY_TRIM = false;
154     private static final boolean DEBUG_PROVIDER = false;
155     private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
156     private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
157     private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
158     private static final int LOG_ON_PAUSE_CALLED = 30021;
159     private static final int LOG_ON_RESUME_CALLED = 30022;
160
161     static ContextImpl mSystemContext = null;
162
163     static IPackageManager sPackageManager;
164
165     final ApplicationThread mAppThread = new ApplicationThread();
166     final Looper mLooper = Looper.myLooper();
167     final H mH = new H();
168     final HashMap<IBinder, ActivityClientRecord> mActivities
169             = new HashMap<IBinder, ActivityClientRecord>();
170     // List of new activities (via ActivityRecord.nextIdle) that should
171     // be reported when next we idle.
172     ActivityClientRecord mNewActivities = null;
173     // Number of activities that are currently visible on-screen.
174     int mNumVisibleActivities = 0;
175     final HashMap<IBinder, Service> mServices
176             = new HashMap<IBinder, Service>();
177     AppBindData mBoundApplication;
178     Profiler mProfiler;
179     int mCurDefaultDisplayDpi;
180     boolean mDensityCompatMode;
181     Configuration mConfiguration;
182     Configuration mCompatConfiguration;
183     Configuration mResConfiguration;
184     CompatibilityInfo mResCompatibilityInfo;
185     Application mInitialApplication;
186     final ArrayList<Application> mAllApplications
187             = new ArrayList<Application>();
188     // set of instantiated backup agents, keyed by package name
189     final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
190     static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>();
191     Instrumentation mInstrumentation;
192     String mInstrumentationAppDir = null;
193     String mInstrumentationAppLibraryDir = null;
194     String mInstrumentationAppPackage = null;
195     String mInstrumentedAppDir = null;
196     String mInstrumentedAppLibraryDir = null;
197     boolean mSystemThread = false;
198     boolean mJitEnabled = false;
199
200     // These can be accessed by multiple threads; mPackages is the lock.
201     // XXX For now we keep around information about all packages we have
202     // seen, not removing entries from this map.
203     // NOTE: The activity and window managers need to call in to
204     // ActivityThread to do things like update resource configurations,
205     // which means this lock gets held while the activity and window managers
206     // holds their own lock.  Thus you MUST NEVER call back into the activity manager
207     // or window manager or anything that depends on them while holding this lock.
208     final HashMap<String, WeakReference<LoadedApk>> mPackages
209             = new HashMap<String, WeakReference<LoadedApk>>();
210     final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
211             = new HashMap<String, WeakReference<LoadedApk>>();
212     final HashMap<CompatibilityInfo, DisplayMetrics> mDefaultDisplayMetrics
213             = new HashMap<CompatibilityInfo, DisplayMetrics>();
214     final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
215             = new HashMap<ResourcesKey, WeakReference<Resources> >();
216     final ArrayList<ActivityClientRecord> mRelaunchingActivities
217             = new ArrayList<ActivityClientRecord>();
218     Configuration mPendingConfiguration = null;
219
220     private static final class ProviderKey {
221         final String authority;
222         final int userId;
223
224         public ProviderKey(String authority, int userId) {
225             this.authority = authority;
226             this.userId = userId;
227         }
228
229         @Override
230         public boolean equals(Object o) {
231             if (o instanceof ProviderKey) {
232                 final ProviderKey other = (ProviderKey) o;
233                 return Objects.equal(authority, other.authority) && userId == other.userId;
234             }
235             return false;
236         }
237
238         @Override
239         public int hashCode() {
240             return ((authority != null) ? authority.hashCode() : 0) ^ userId;
241         }
242     }
243
244     // The lock of mProviderMap protects the following variables.
245     final HashMap<ProviderKey, ProviderClientRecord> mProviderMap
246         = new HashMap<ProviderKey, ProviderClientRecord>();
247     final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
248         = new HashMap<IBinder, ProviderRefCount>();
249     final HashMap<IBinder, ProviderClientRecord> mLocalProviders
250         = new HashMap<IBinder, ProviderClientRecord>();
251     final HashMap<ComponentName, ProviderClientRecord> mLocalProvidersByName
252             = new HashMap<ComponentName, ProviderClientRecord>();
253
254     final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
255         = new HashMap<Activity, ArrayList<OnActivityPausedListener>>();
256
257     final GcIdler mGcIdler = new GcIdler();
258     boolean mGcIdlerScheduled = false;
259
260     static Handler sMainThreadHandler;  // set once in main()
261
262     Bundle mCoreSettings = null;
263
264     static final class ActivityClientRecord {
265         IBinder token;
266         int ident;
267         Intent intent;
268         Bundle state;
269         Activity activity;
270         Window window;
271         Activity parent;
272         String embeddedID;
273         Activity.NonConfigurationInstances lastNonConfigurationInstances;
274         boolean paused;
275         boolean stopped;
276         boolean hideForNow;
277         Configuration newConfig;
278         Configuration createdConfig;
279         ActivityClientRecord nextIdle;
280
281         String profileFile;
282         ParcelFileDescriptor profileFd;
283         boolean autoStopProfiler;
284
285         ActivityInfo activityInfo;
286         CompatibilityInfo compatInfo;
287         LoadedApk packageInfo;
288
289         List<ResultInfo> pendingResults;
290         List<Intent> pendingIntents;
291
292         boolean startsNotResumed;
293         boolean isForward;
294         int pendingConfigChanges;
295         boolean onlyLocalRequest;
296
297         View mPendingRemoveWindow;
298         WindowManager mPendingRemoveWindowManager;
299
300         ActivityClientRecord() {
301             parent = null;
302             embeddedID = null;
303             paused = false;
304             stopped = false;
305             hideForNow = false;
306             nextIdle = null;
307         }
308
309         public boolean isPreHoneycomb() {
310             if (activity != null) {
311                 return activity.getApplicationInfo().targetSdkVersion
312                         < android.os.Build.VERSION_CODES.HONEYCOMB;
313             }
314             return false;
315         }
316
317         public String toString() {
318             ComponentName componentName = intent != null ? intent.getComponent() : null;
319             return "ActivityRecord{"
320                 + Integer.toHexString(System.identityHashCode(this))
321                 + " token=" + token + " " + (componentName == null
322                         ? "no component name" : componentName.toShortString())
323                 + "}";
324         }
325     }
326
327     final class ProviderClientRecord {
328         final String[] mNames;
329         final IContentProvider mProvider;
330         final ContentProvider mLocalProvider;
331         final IActivityManager.ContentProviderHolder mHolder;
332
333         ProviderClientRecord(String[] names, IContentProvider provider,
334                 ContentProvider localProvider,
335                 IActivityManager.ContentProviderHolder holder) {
336             mNames = names;
337             mProvider = provider;
338             mLocalProvider = localProvider;
339             mHolder = holder;
340         }
341     }
342
343     static final class NewIntentData {
344         List<Intent> intents;
345         IBinder token;
346         public String toString() {
347             return "NewIntentData{intents=" + intents + " token=" + token + "}";
348         }
349     }
350
351     static final class ReceiverData extends BroadcastReceiver.PendingResult {
352         public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
353                 boolean ordered, boolean sticky, IBinder token, int sendingUser) {
354             super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,
355                     token, sendingUser);
356             this.intent = intent;
357         }
358
359         Intent intent;
360         ActivityInfo info;
361         CompatibilityInfo compatInfo;
362         public String toString() {
363             return "ReceiverData{intent=" + intent + " packageName=" +
364                     info.packageName + " resultCode=" + getResultCode()
365                     + " resultData=" + getResultData() + " resultExtras="
366                     + getResultExtras(false) + "}";
367         }
368     }
369
370     static final class CreateBackupAgentData {
371         ApplicationInfo appInfo;
372         CompatibilityInfo compatInfo;
373         int backupMode;
374         public String toString() {
375             return "CreateBackupAgentData{appInfo=" + appInfo
376                     + " backupAgent=" + appInfo.backupAgentName
377                     + " mode=" + backupMode + "}";
378         }
379     }
380
381     static final class CreateServiceData {
382         IBinder token;
383         ServiceInfo info;
384         CompatibilityInfo compatInfo;
385         Intent intent;
386         public String toString() {
387             return "CreateServiceData{token=" + token + " className="
388             + info.name + " packageName=" + info.packageName
389             + " intent=" + intent + "}";
390         }
391     }
392
393     static final class BindServiceData {
394         IBinder token;
395         Intent intent;
396         boolean rebind;
397         public String toString() {
398             return "BindServiceData{token=" + token + " intent=" + intent + "}";
399         }
400     }
401
402     static final class ServiceArgsData {
403         IBinder token;
404         boolean taskRemoved;
405         int startId;
406         int flags;
407         Intent args;
408         public String toString() {
409             return "ServiceArgsData{token=" + token + " startId=" + startId
410             + " args=" + args + "}";
411         }
412     }
413
414     static final class AppBindData {
415         LoadedApk info;
416         String processName;
417         ApplicationInfo appInfo;
418         List<ProviderInfo> providers;
419         ComponentName instrumentationName;
420         Bundle instrumentationArgs;
421         IInstrumentationWatcher instrumentationWatcher;
422         int debugMode;
423         boolean enableOpenGlTrace;
424         boolean restrictedBackupMode;
425         boolean persistent;
426         Configuration config;
427         CompatibilityInfo compatInfo;
428
429         /** Initial values for {@link Profiler}. */
430         String initProfileFile;
431         ParcelFileDescriptor initProfileFd;
432         boolean initAutoStopProfiler;
433
434         public String toString() {
435             return "AppBindData{appInfo=" + appInfo + "}";
436         }
437     }
438
439     static final class Profiler {
440         String profileFile;
441         ParcelFileDescriptor profileFd;
442         boolean autoStopProfiler;
443         boolean profiling;
444         boolean handlingProfiling;
445         public void setProfiler(String file, ParcelFileDescriptor fd) {
446             if (profiling) {
447                 if (fd != null) {
448                     try {
449                         fd.close();
450                     } catch (IOException e) {
451                         // Ignore
452                     }
453                 }
454                 return;
455             }
456             if (profileFd != null) {
457                 try {
458                     profileFd.close();
459                 } catch (IOException e) {
460                     // Ignore
461                 }
462             }
463             profileFile = file;
464             profileFd = fd;
465         }
466         public void startProfiling() {
467             if (profileFd == null || profiling) {
468                 return;
469             }
470             try {
471                 Debug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
472                         8 * 1024 * 1024, 0);
473                 profiling = true;
474             } catch (RuntimeException e) {
475                 Slog.w(TAG, "Profiling failed on path " + profileFile);
476                 try {
477                     profileFd.close();
478                     profileFd = null;
479                 } catch (IOException e2) {
480                     Slog.w(TAG, "Failure closing profile fd", e2);
481                 }
482             }
483         }
484         public void stopProfiling() {
485             if (profiling) {
486                 profiling = false;
487                 Debug.stopMethodTracing();
488                 if (profileFd != null) {
489                     try {
490                         profileFd.close();
491                     } catch (IOException e) {
492                     }
493                 }
494                 profileFd = null;
495                 profileFile = null;
496             }
497         }
498     }
499
500     static final class DumpComponentInfo {
501         ParcelFileDescriptor fd;
502         IBinder token;
503         String prefix;
504         String[] args;
505     }
506
507     static final class ResultData {
508         IBinder token;
509         List<ResultInfo> results;
510         public String toString() {
511             return "ResultData{token=" + token + " results" + results + "}";
512         }
513     }
514
515     static final class ContextCleanupInfo {
516         ContextImpl context;
517         String what;
518         String who;
519     }
520
521     static final class ProfilerControlData {
522         String path;
523         ParcelFileDescriptor fd;
524     }
525
526     static final class DumpHeapData {
527         String path;
528         ParcelFileDescriptor fd;
529     }
530
531     static final class UpdateCompatibilityData {
532         String pkg;
533         CompatibilityInfo info;
534     }
535     
536     private native void dumpGraphicsInfo(FileDescriptor fd);
537
538     private class ApplicationThread extends ApplicationThreadNative {
539         private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s";
540         private static final String ONE_COUNT_COLUMN = "%21s %8d";
541         private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
542         private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";
543
544         // Formatting for checkin service - update version if row format changes
545         private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
546
547         private void updatePendingConfiguration(Configuration config) {
548             synchronized (mPackages) {
549                 if (mPendingConfiguration == null ||
550                         mPendingConfiguration.isOtherSeqNewer(config)) {
551                     mPendingConfiguration = config;
552                 }
553             }
554         }
555
556         public final void schedulePauseActivity(IBinder token, boolean finished,
557                 boolean userLeaving, int configChanges) {
558             queueOrSendMessage(
559                     finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
560                     token,
561                     (userLeaving ? 1 : 0),
562                     configChanges);
563         }
564
565         public final void scheduleStopActivity(IBinder token, boolean showWindow,
566                 int configChanges) {
567            queueOrSendMessage(
568                 showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
569                 token, 0, configChanges);
570         }
571
572         public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
573             queueOrSendMessage(
574                 showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
575                 token);
576         }
577
578         public final void scheduleSleeping(IBinder token, boolean sleeping) {
579             queueOrSendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
580         }
581
582         public final void scheduleResumeActivity(IBinder token, boolean isForward) {
583             queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
584         }
585
586         public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
587             ResultData res = new ResultData();
588             res.token = token;
589             res.results = results;
590             queueOrSendMessage(H.SEND_RESULT, res);
591         }
592
593         // we use token to identify this activity without having to send the
594         // activity itself back to the activity manager. (matters more with ipc)
595         public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
596                 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
597                 Bundle state, List<ResultInfo> pendingResults,
598                 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
599                 String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
600             ActivityClientRecord r = new ActivityClientRecord();
601
602             r.token = token;
603             r.ident = ident;
604             r.intent = intent;
605             r.activityInfo = info;
606             r.compatInfo = compatInfo;
607             r.state = state;
608
609             r.pendingResults = pendingResults;
610             r.pendingIntents = pendingNewIntents;
611
612             r.startsNotResumed = notResumed;
613             r.isForward = isForward;
614
615             r.profileFile = profileName;
616             r.profileFd = profileFd;
617             r.autoStopProfiler = autoStopProfiler;
618
619             updatePendingConfiguration(curConfig);
620
621             queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
622         }
623
624         public final void scheduleRelaunchActivity(IBinder token,
625                 List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
626                 int configChanges, boolean notResumed, Configuration config) {
627             requestRelaunchActivity(token, pendingResults, pendingNewIntents,
628                     configChanges, notResumed, config, true);
629         }
630
631         public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
632             NewIntentData data = new NewIntentData();
633             data.intents = intents;
634             data.token = token;
635
636             queueOrSendMessage(H.NEW_INTENT, data);
637         }
638
639         public final void scheduleDestroyActivity(IBinder token, boolean finishing,
640                 int configChanges) {
641             queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
642                     configChanges);
643         }
644
645         public final void scheduleReceiver(Intent intent, ActivityInfo info,
646                 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
647                 boolean sync, int sendingUser) {
648             ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
649                     sync, false, mAppThread.asBinder(), sendingUser);
650             r.info = info;
651             r.compatInfo = compatInfo;
652             queueOrSendMessage(H.RECEIVER, r);
653         }
654
655         public final void scheduleCreateBackupAgent(ApplicationInfo app,
656                 CompatibilityInfo compatInfo, int backupMode) {
657             CreateBackupAgentData d = new CreateBackupAgentData();
658             d.appInfo = app;
659             d.compatInfo = compatInfo;
660             d.backupMode = backupMode;
661
662             queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
663         }
664
665         public final void scheduleDestroyBackupAgent(ApplicationInfo app,
666                 CompatibilityInfo compatInfo) {
667             CreateBackupAgentData d = new CreateBackupAgentData();
668             d.appInfo = app;
669             d.compatInfo = compatInfo;
670
671             queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
672         }
673
674         public final void scheduleCreateService(IBinder token,
675                 ServiceInfo info, CompatibilityInfo compatInfo) {
676             CreateServiceData s = new CreateServiceData();
677             s.token = token;
678             s.info = info;
679             s.compatInfo = compatInfo;
680
681             queueOrSendMessage(H.CREATE_SERVICE, s);
682         }
683
684         public final void scheduleBindService(IBinder token, Intent intent,
685                 boolean rebind) {
686             BindServiceData s = new BindServiceData();
687             s.token = token;
688             s.intent = intent;
689             s.rebind = rebind;
690
691             if (DEBUG_SERVICE)
692                 Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
693                         + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
694             queueOrSendMessage(H.BIND_SERVICE, s);
695         }
696
697         public final void scheduleUnbindService(IBinder token, Intent intent) {
698             BindServiceData s = new BindServiceData();
699             s.token = token;
700             s.intent = intent;
701
702             queueOrSendMessage(H.UNBIND_SERVICE, s);
703         }
704
705         public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
706             int flags ,Intent args) {
707             ServiceArgsData s = new ServiceArgsData();
708             s.token = token;
709             s.taskRemoved = taskRemoved;
710             s.startId = startId;
711             s.flags = flags;
712             s.args = args;
713
714             queueOrSendMessage(H.SERVICE_ARGS, s);
715         }
716
717         public final void scheduleStopService(IBinder token) {
718             queueOrSendMessage(H.STOP_SERVICE, token);
719         }
720
721         public final void bindApplication(String processName,
722                 ApplicationInfo appInfo, List<ProviderInfo> providers,
723                 ComponentName instrumentationName, String profileFile,
724                 ParcelFileDescriptor profileFd, boolean autoStopProfiler,
725                 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
726                 int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode,
727                 boolean persistent, Configuration config, CompatibilityInfo compatInfo,
728                 Map<String, IBinder> services, Bundle coreSettings) {
729
730             if (services != null) {
731                 // Setup the service cache in the ServiceManager
732                 ServiceManager.initServiceCache(services);
733             }
734
735             setCoreSettings(coreSettings);
736
737             AppBindData data = new AppBindData();
738             data.processName = processName;
739             data.appInfo = appInfo;
740             data.providers = providers;
741             data.instrumentationName = instrumentationName;
742             data.instrumentationArgs = instrumentationArgs;
743             data.instrumentationWatcher = instrumentationWatcher;
744             data.debugMode = debugMode;
745             data.enableOpenGlTrace = enableOpenGlTrace;
746             data.restrictedBackupMode = isRestrictedBackupMode;
747             data.persistent = persistent;
748             data.config = config;
749             data.compatInfo = compatInfo;
750             data.initProfileFile = profileFile;
751             data.initProfileFd = profileFd;
752             data.initAutoStopProfiler = false;
753             queueOrSendMessage(H.BIND_APPLICATION, data);
754         }
755
756         public final void scheduleExit() {
757             queueOrSendMessage(H.EXIT_APPLICATION, null);
758         }
759
760         public final void scheduleSuicide() {
761             queueOrSendMessage(H.SUICIDE, null);
762         }
763
764         public void requestThumbnail(IBinder token) {
765             queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
766         }
767
768         public void scheduleConfigurationChanged(Configuration config) {
769             updatePendingConfiguration(config);
770             queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
771         }
772
773         public void updateTimeZone() {
774             TimeZone.setDefault(null);
775         }
776
777         public void clearDnsCache() {
778             // a non-standard API to get this to libcore
779             InetAddress.clearDnsCache();
780         }
781
782         public void setHttpProxy(String host, String port, String exclList) {
783             Proxy.setHttpProxySystemProperty(host, port, exclList);
784         }
785
786         public void processInBackground() {
787             mH.removeMessages(H.GC_WHEN_IDLE);
788             mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
789         }
790
791         public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
792             DumpComponentInfo data = new DumpComponentInfo();
793             try {
794                 data.fd = ParcelFileDescriptor.dup(fd);
795                 data.token = servicetoken;
796                 data.args = args;
797                 queueOrSendMessage(H.DUMP_SERVICE, data);
798             } catch (IOException e) {
799                 Slog.w(TAG, "dumpService failed", e);
800             }
801         }
802
803         // This function exists to make sure all receiver dispatching is
804         // correctly ordered, since these are one-way calls and the binder driver
805         // applies transaction ordering per object for such calls.
806         public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
807                 int resultCode, String dataStr, Bundle extras, boolean ordered,
808                 boolean sticky, int sendingUser) throws RemoteException {
809             receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
810                     sticky, sendingUser);
811         }
812
813         public void scheduleLowMemory() {
814             queueOrSendMessage(H.LOW_MEMORY, null);
815         }
816
817         public void scheduleActivityConfigurationChanged(IBinder token) {
818             queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
819         }
820
821         public void profilerControl(boolean start, String path, ParcelFileDescriptor fd,
822                 int profileType) {
823             ProfilerControlData pcd = new ProfilerControlData();
824             pcd.path = path;
825             pcd.fd = fd;
826             queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType);
827         }
828
829         public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) {
830             DumpHeapData dhd = new DumpHeapData();
831             dhd.path = path;
832             dhd.fd = fd;
833             queueOrSendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0);
834         }
835
836         public void setSchedulingGroup(int group) {
837             // Note: do this immediately, since going into the foreground
838             // should happen regardless of what pending work we have to do
839             // and the activity manager will wait for us to report back that
840             // we are done before sending us to the background.
841             try {
842                 Process.setProcessGroup(Process.myPid(), group);
843             } catch (Exception e) {
844                 Slog.w(TAG, "Failed setting process group to " + group, e);
845             }
846         }
847
848         public void getMemoryInfo(Debug.MemoryInfo outInfo) {
849             Debug.getMemoryInfo(outInfo);
850         }
851
852         public void dispatchPackageBroadcast(int cmd, String[] packages) {
853             queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
854         }
855
856         public void scheduleCrash(String msg) {
857             queueOrSendMessage(H.SCHEDULE_CRASH, msg);
858         }
859
860         public void dumpActivity(FileDescriptor fd, IBinder activitytoken,
861                 String prefix, String[] args) {
862             DumpComponentInfo data = new DumpComponentInfo();
863             try {
864                 data.fd = ParcelFileDescriptor.dup(fd);
865                 data.token = activitytoken;
866                 data.prefix = prefix;
867                 data.args = args;
868                 queueOrSendMessage(H.DUMP_ACTIVITY, data);
869             } catch (IOException e) {
870                 Slog.w(TAG, "dumpActivity failed", e);
871             }
872         }
873
874         public void dumpProvider(FileDescriptor fd, IBinder providertoken,
875                 String[] args) {
876             DumpComponentInfo data = new DumpComponentInfo();
877             try {
878                 data.fd = ParcelFileDescriptor.dup(fd);
879                 data.token = providertoken;
880                 data.args = args;
881                 queueOrSendMessage(H.DUMP_PROVIDER, data);
882             } catch (IOException e) {
883                 Slog.w(TAG, "dumpProvider failed", e);
884             }
885         }
886
887         @Override
888         public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin,
889                 boolean all, String[] args) {
890             FileOutputStream fout = new FileOutputStream(fd);
891             PrintWriter pw = new PrintWriter(fout);
892             try {
893                 return dumpMemInfo(pw, checkin, all);
894             } finally {
895                 pw.flush();
896             }
897         }
898
899         private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, boolean checkin, boolean all) {
900             long nativeMax = Debug.getNativeHeapSize() / 1024;
901             long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
902             long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
903
904             Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
905             Debug.getMemoryInfo(memInfo);
906
907             if (!all) {
908                 return memInfo;
909             }
910
911             Runtime runtime = Runtime.getRuntime();
912
913             long dalvikMax = runtime.totalMemory() / 1024;
914             long dalvikFree = runtime.freeMemory() / 1024;
915             long dalvikAllocated = dalvikMax - dalvikFree;
916             long viewInstanceCount = ViewDebug.getViewInstanceCount();
917             long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
918             long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class);
919             long activityInstanceCount = Debug.countInstancesOfClass(Activity.class);
920             int globalAssetCount = AssetManager.getGlobalAssetCount();
921             int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
922             int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
923             int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
924             int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
925             long openSslSocketCount = Debug.countInstancesOfClass(OpenSSLSocketImpl.class);
926             SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
927
928             // For checkin, we print one long comma-separated list of values
929             if (checkin) {
930                 // NOTE: if you change anything significant below, also consider changing
931                 // ACTIVITY_THREAD_CHECKIN_VERSION.
932                 String processName = (mBoundApplication != null)
933                         ? mBoundApplication.processName : "unknown";
934
935                 // Header
936                 pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
937                 pw.print(Process.myPid()); pw.print(',');
938                 pw.print(processName); pw.print(',');
939
940                 // Heap info - max
941                 pw.print(nativeMax); pw.print(',');
942                 pw.print(dalvikMax); pw.print(',');
943                 pw.print("N/A,");
944                 pw.print(nativeMax + dalvikMax); pw.print(',');
945
946                 // Heap info - allocated
947                 pw.print(nativeAllocated); pw.print(',');
948                 pw.print(dalvikAllocated); pw.print(',');
949                 pw.print("N/A,");
950                 pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
951
952                 // Heap info - free
953                 pw.print(nativeFree); pw.print(',');
954                 pw.print(dalvikFree); pw.print(',');
955                 pw.print("N/A,");
956                 pw.print(nativeFree + dalvikFree); pw.print(',');
957
958                 // Heap info - proportional set size
959                 pw.print(memInfo.nativePss); pw.print(',');
960                 pw.print(memInfo.dalvikPss); pw.print(',');
961                 pw.print(memInfo.otherPss); pw.print(',');
962                 pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
963
964                 // Heap info - shared
965                 pw.print(memInfo.nativeSharedDirty); pw.print(',');
966                 pw.print(memInfo.dalvikSharedDirty); pw.print(',');
967                 pw.print(memInfo.otherSharedDirty); pw.print(',');
968                 pw.print(memInfo.nativeSharedDirty + memInfo.dalvikSharedDirty
969                         + memInfo.otherSharedDirty); pw.print(',');
970
971                 // Heap info - private
972                 pw.print(memInfo.nativePrivateDirty); pw.print(',');
973                 pw.print(memInfo.dalvikPrivateDirty); pw.print(',');
974                 pw.print(memInfo.otherPrivateDirty); pw.print(',');
975                 pw.print(memInfo.nativePrivateDirty + memInfo.dalvikPrivateDirty
976                         + memInfo.otherPrivateDirty); pw.print(',');
977
978                 // Object counts
979                 pw.print(viewInstanceCount); pw.print(',');
980                 pw.print(viewRootInstanceCount); pw.print(',');
981                 pw.print(appContextInstanceCount); pw.print(',');
982                 pw.print(activityInstanceCount); pw.print(',');
983
984                 pw.print(globalAssetCount); pw.print(',');
985                 pw.print(globalAssetManagerCount); pw.print(',');
986                 pw.print(binderLocalObjectCount); pw.print(',');
987                 pw.print(binderProxyObjectCount); pw.print(',');
988
989                 pw.print(binderDeathObjectCount); pw.print(',');
990                 pw.print(openSslSocketCount); pw.print(',');
991
992                 // SQL
993                 pw.print(stats.memoryUsed / 1024); pw.print(',');
994                 pw.print(stats.memoryUsed / 1024); pw.print(',');
995                 pw.print(stats.pageCacheOverflow / 1024); pw.print(',');
996                 pw.print(stats.largestMemAlloc / 1024);
997                 for (int i = 0; i < stats.dbStats.size(); i++) {
998                     DbStats dbStats = stats.dbStats.get(i);
999                     pw.print(','); pw.print(dbStats.dbName);
1000                     pw.print(','); pw.print(dbStats.pageSize);
1001                     pw.print(','); pw.print(dbStats.dbSize);
1002                     pw.print(','); pw.print(dbStats.lookaside);
1003                     pw.print(','); pw.print(dbStats.cache);
1004                     pw.print(','); pw.print(dbStats.cache);
1005                 }
1006                 pw.println();
1007
1008                 return memInfo;
1009             }
1010
1011             // otherwise, show human-readable format
1012             printRow(pw, HEAP_COLUMN, "", "", "Shared", "Private", "Heap", "Heap", "Heap");
1013             printRow(pw, HEAP_COLUMN, "", "Pss", "Dirty", "Dirty", "Size", "Alloc", "Free");
1014             printRow(pw, HEAP_COLUMN, "", "------", "------", "------", "------", "------",
1015                     "------");
1016             printRow(pw, HEAP_COLUMN, "Native", memInfo.nativePss, memInfo.nativeSharedDirty,
1017                     memInfo.nativePrivateDirty, nativeMax, nativeAllocated, nativeFree);
1018             printRow(pw, HEAP_COLUMN, "Dalvik", memInfo.dalvikPss, memInfo.dalvikSharedDirty,
1019                     memInfo.dalvikPrivateDirty, dalvikMax, dalvikAllocated, dalvikFree);
1020
1021             int otherPss = memInfo.otherPss;
1022             int otherSharedDirty = memInfo.otherSharedDirty;
1023             int otherPrivateDirty = memInfo.otherPrivateDirty;
1024
1025             for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
1026                 printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
1027                         memInfo.getOtherPss(i), memInfo.getOtherSharedDirty(i),
1028                         memInfo.getOtherPrivateDirty(i), "", "", "");
1029                 otherPss -= memInfo.getOtherPss(i);
1030                 otherSharedDirty -= memInfo.getOtherSharedDirty(i);
1031                 otherPrivateDirty -= memInfo.getOtherPrivateDirty(i);
1032             }
1033
1034             printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSharedDirty,
1035                     otherPrivateDirty, "", "", "");
1036             printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
1037                     memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
1038                     nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
1039                     nativeFree+dalvikFree);
1040
1041             pw.println(" ");
1042             pw.println(" Objects");
1043             printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:",
1044                     viewRootInstanceCount);
1045
1046             printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
1047                     "Activities:", activityInstanceCount);
1048
1049             printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
1050                     "AssetManagers:", globalAssetManagerCount);
1051
1052             printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
1053                     "Proxy Binders:", binderProxyObjectCount);
1054             printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
1055
1056             printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
1057
1058             // SQLite mem info
1059             pw.println(" ");
1060             pw.println(" SQL");
1061             printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024);
1062             printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:",
1063                     stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
1064             pw.println(" ");
1065             int N = stats.dbStats.size();
1066             if (N > 0) {
1067                 pw.println(" DATABASES");
1068                 printRow(pw, "  %8s %8s %14s %14s  %s", "pgsz", "dbsz", "Lookaside(b)", "cache",
1069                         "Dbname");
1070                 for (int i = 0; i < N; i++) {
1071                     DbStats dbStats = stats.dbStats.get(i);
1072                     printRow(pw, DB_INFO_FORMAT,
1073                             (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
1074                             (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
1075                             (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
1076                             dbStats.cache, dbStats.dbName);
1077                 }
1078             }
1079
1080             // Asset details.
1081             String assetAlloc = AssetManager.getAssetAllocations();
1082             if (assetAlloc != null) {
1083                 pw.println(" ");
1084                 pw.println(" Asset Allocations");
1085                 pw.print(assetAlloc);
1086             }
1087
1088             return memInfo;
1089         }
1090
1091         @Override
1092         public void dumpGfxInfo(FileDescriptor fd, String[] args) {
1093             dumpGraphicsInfo(fd);
1094             WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
1095         }
1096
1097         @Override
1098         public void dumpDbInfo(FileDescriptor fd, String[] args) {
1099             PrintWriter pw = new PrintWriter(new FileOutputStream(fd));
1100             PrintWriterPrinter printer = new PrintWriterPrinter(pw);
1101             SQLiteDebug.dump(printer, args);
1102             pw.flush();
1103         }
1104
1105         @Override
1106         public void unstableProviderDied(IBinder provider) {
1107             queueOrSendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
1108         }
1109
1110         private void printRow(PrintWriter pw, String format, Object...objs) {
1111             pw.println(String.format(format, objs));
1112         }
1113
1114         public void setCoreSettings(Bundle coreSettings) {
1115             queueOrSendMessage(H.SET_CORE_SETTINGS, coreSettings);
1116         }
1117
1118         public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) {
1119             UpdateCompatibilityData ucd = new UpdateCompatibilityData();
1120             ucd.pkg = pkg;
1121             ucd.info = info;
1122             queueOrSendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
1123         }
1124
1125         public void scheduleTrimMemory(int level) {
1126             queueOrSendMessage(H.TRIM_MEMORY, null, level);
1127         }
1128
1129     }
1130
1131     private class H extends Handler {
1132         public static final int LAUNCH_ACTIVITY         = 100;
1133         public static final int PAUSE_ACTIVITY          = 101;
1134         public static final int PAUSE_ACTIVITY_FINISHING= 102;
1135         public static final int STOP_ACTIVITY_SHOW      = 103;
1136         public static final int STOP_ACTIVITY_HIDE      = 104;
1137         public static final int SHOW_WINDOW             = 105;
1138         public static final int HIDE_WINDOW             = 106;
1139         public static final int RESUME_ACTIVITY         = 107;
1140         public static final int SEND_RESULT             = 108;
1141         public static final int DESTROY_ACTIVITY        = 109;
1142         public static final int BIND_APPLICATION        = 110;
1143         public static final int EXIT_APPLICATION        = 111;
1144         public static final int NEW_INTENT              = 112;
1145         public static final int RECEIVER                = 113;
1146         public static final int CREATE_SERVICE          = 114;
1147         public static final int SERVICE_ARGS            = 115;
1148         public static final int STOP_SERVICE            = 116;
1149         public static final int REQUEST_THUMBNAIL       = 117;
1150         public static final int CONFIGURATION_CHANGED   = 118;
1151         public static final int CLEAN_UP_CONTEXT        = 119;
1152         public static final int GC_WHEN_IDLE            = 120;
1153         public static final int BIND_SERVICE            = 121;
1154         public static final int UNBIND_SERVICE          = 122;
1155         public static final int DUMP_SERVICE            = 123;
1156         public static final int LOW_MEMORY              = 124;
1157         public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
1158         public static final int RELAUNCH_ACTIVITY       = 126;
1159         public static final int PROFILER_CONTROL        = 127;
1160         public static final int CREATE_BACKUP_AGENT     = 128;
1161         public static final int DESTROY_BACKUP_AGENT    = 129;
1162         public static final int SUICIDE                 = 130;
1163         public static final int REMOVE_PROVIDER         = 131;
1164         public static final int ENABLE_JIT              = 132;
1165         public static final int DISPATCH_PACKAGE_BROADCAST = 133;
1166         public static final int SCHEDULE_CRASH          = 134;
1167         public static final int DUMP_HEAP               = 135;
1168         public static final int DUMP_ACTIVITY           = 136;
1169         public static final int SLEEPING                = 137;
1170         public static final int SET_CORE_SETTINGS       = 138;
1171         public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
1172         public static final int TRIM_MEMORY             = 140;
1173         public static final int DUMP_PROVIDER           = 141;
1174         public static final int UNSTABLE_PROVIDER_DIED  = 142;
1175         String codeToString(int code) {
1176             if (DEBUG_MESSAGES) {
1177                 switch (code) {
1178                     case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
1179                     case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
1180                     case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
1181                     case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
1182                     case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
1183                     case SHOW_WINDOW: return "SHOW_WINDOW";
1184                     case HIDE_WINDOW: return "HIDE_WINDOW";
1185                     case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
1186                     case SEND_RESULT: return "SEND_RESULT";
1187                     case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
1188                     case BIND_APPLICATION: return "BIND_APPLICATION";
1189                     case EXIT_APPLICATION: return "EXIT_APPLICATION";
1190                     case NEW_INTENT: return "NEW_INTENT";
1191                     case RECEIVER: return "RECEIVER";
1192                     case CREATE_SERVICE: return "CREATE_SERVICE";
1193                     case SERVICE_ARGS: return "SERVICE_ARGS";
1194                     case STOP_SERVICE: return "STOP_SERVICE";
1195                     case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
1196                     case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
1197                     case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
1198                     case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
1199                     case BIND_SERVICE: return "BIND_SERVICE";
1200                     case UNBIND_SERVICE: return "UNBIND_SERVICE";
1201                     case DUMP_SERVICE: return "DUMP_SERVICE";
1202                     case LOW_MEMORY: return "LOW_MEMORY";
1203                     case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
1204                     case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
1205                     case PROFILER_CONTROL: return "PROFILER_CONTROL";
1206                     case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
1207                     case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
1208                     case SUICIDE: return "SUICIDE";
1209                     case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
1210                     case ENABLE_JIT: return "ENABLE_JIT";
1211                     case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
1212                     case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
1213                     case DUMP_HEAP: return "DUMP_HEAP";
1214                     case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
1215                     case SLEEPING: return "SLEEPING";
1216                     case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
1217                     case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
1218                     case TRIM_MEMORY: return "TRIM_MEMORY";
1219                     case DUMP_PROVIDER: return "DUMP_PROVIDER";
1220                     case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
1221                 }
1222             }
1223             return Integer.toString(code);
1224         }
1225         public void handleMessage(Message msg) {
1226             if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
1227             switch (msg.what) {
1228                 case LAUNCH_ACTIVITY: {
1229                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
1230                     ActivityClientRecord r = (ActivityClientRecord)msg.obj;
1231
1232                     r.packageInfo = getPackageInfoNoCheck(
1233                             r.activityInfo.applicationInfo, r.compatInfo);
1234                     handleLaunchActivity(r, null);
1235                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1236                 } break;
1237                 case RELAUNCH_ACTIVITY: {
1238                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
1239                     ActivityClientRecord r = (ActivityClientRecord)msg.obj;
1240                     handleRelaunchActivity(r);
1241                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1242                 } break;
1243                 case PAUSE_ACTIVITY:
1244                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
1245                     handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
1246                     maybeSnapshot();
1247                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1248                     break;
1249                 case PAUSE_ACTIVITY_FINISHING:
1250                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
1251                     handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
1252                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1253                     break;
1254                 case STOP_ACTIVITY_SHOW:
1255                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
1256                     handleStopActivity((IBinder)msg.obj, true, msg.arg2);
1257                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1258                     break;
1259                 case STOP_ACTIVITY_HIDE:
1260                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
1261                     handleStopActivity((IBinder)msg.obj, false, msg.arg2);
1262                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1263                     break;
1264                 case SHOW_WINDOW:
1265                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
1266                     handleWindowVisibility((IBinder)msg.obj, true);
1267                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1268                     break;
1269                 case HIDE_WINDOW:
1270                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
1271                     handleWindowVisibility((IBinder)msg.obj, false);
1272                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1273                     break;
1274                 case RESUME_ACTIVITY:
1275                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
1276                     handleResumeActivity((IBinder)msg.obj, true,
1277                             msg.arg1 != 0, true);
1278                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1279                     break;
1280                 case SEND_RESULT:
1281                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
1282                     handleSendResult((ResultData)msg.obj);
1283                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1284                     break;
1285                 case DESTROY_ACTIVITY:
1286                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
1287                     handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
1288                             msg.arg2, false);
1289                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1290                     break;
1291                 case BIND_APPLICATION:
1292                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
1293                     AppBindData data = (AppBindData)msg.obj;
1294                     handleBindApplication(data);
1295                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1296                     break;
1297                 case EXIT_APPLICATION:
1298                     if (mInitialApplication != null) {
1299                         mInitialApplication.onTerminate();
1300                     }
1301                     Looper.myLooper().quit();
1302                     break;
1303                 case NEW_INTENT:
1304                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
1305                     handleNewIntent((NewIntentData)msg.obj);
1306                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1307                     break;
1308                 case RECEIVER:
1309                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
1310                     handleReceiver((ReceiverData)msg.obj);
1311                     maybeSnapshot();
1312                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1313                     break;
1314                 case CREATE_SERVICE:
1315                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
1316                     handleCreateService((CreateServiceData)msg.obj);
1317                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1318                     break;
1319                 case BIND_SERVICE:
1320                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
1321                     handleBindService((BindServiceData)msg.obj);
1322                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1323                     break;
1324                 case UNBIND_SERVICE:
1325                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
1326                     handleUnbindService((BindServiceData)msg.obj);
1327                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1328                     break;
1329                 case SERVICE_ARGS:
1330                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
1331                     handleServiceArgs((ServiceArgsData)msg.obj);
1332                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1333                     break;
1334                 case STOP_SERVICE:
1335                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
1336                     handleStopService((IBinder)msg.obj);
1337                     maybeSnapshot();
1338                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1339                     break;
1340                 case REQUEST_THUMBNAIL:
1341                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestThumbnail");
1342                     handleRequestThumbnail((IBinder)msg.obj);
1343                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1344                     break;
1345                 case CONFIGURATION_CHANGED:
1346                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
1347                     mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
1348                     handleConfigurationChanged((Configuration)msg.obj, null);
1349                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1350                     break;
1351                 case CLEAN_UP_CONTEXT:
1352                     ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
1353                     cci.context.performFinalCleanup(cci.who, cci.what);
1354                     break;
1355                 case GC_WHEN_IDLE:
1356                     scheduleGcIdler();
1357                     break;
1358                 case DUMP_SERVICE:
1359                     handleDumpService((DumpComponentInfo)msg.obj);
1360                     break;
1361                 case LOW_MEMORY:
1362                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
1363                     handleLowMemory();
1364                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1365                     break;
1366                 case ACTIVITY_CONFIGURATION_CHANGED:
1367                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
1368                     handleActivityConfigurationChanged((IBinder)msg.obj);
1369                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1370                     break;
1371                 case PROFILER_CONTROL:
1372                     handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2);
1373                     break;
1374                 case CREATE_BACKUP_AGENT:
1375                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
1376                     handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
1377                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1378                     break;
1379                 case DESTROY_BACKUP_AGENT:
1380                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
1381                     handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
1382                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1383                     break;
1384                 case SUICIDE:
1385                     Process.killProcess(Process.myPid());
1386                     break;
1387                 case REMOVE_PROVIDER:
1388                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
1389                     completeRemoveProvider((ProviderRefCount)msg.obj);
1390                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1391                     break;
1392                 case ENABLE_JIT:
1393                     ensureJitEnabled();
1394                     break;
1395                 case DISPATCH_PACKAGE_BROADCAST:
1396                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
1397                     handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
1398                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1399                     break;
1400                 case SCHEDULE_CRASH:
1401                     throw new RemoteServiceException((String)msg.obj);
1402                 case DUMP_HEAP:
1403                     handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
1404                     break;
1405                 case DUMP_ACTIVITY:
1406                     handleDumpActivity((DumpComponentInfo)msg.obj);
1407                     break;
1408                 case DUMP_PROVIDER:
1409                     handleDumpProvider((DumpComponentInfo)msg.obj);
1410                     break;
1411                 case SLEEPING:
1412                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
1413                     handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
1414                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1415                     break;
1416                 case SET_CORE_SETTINGS:
1417                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
1418                     handleSetCoreSettings((Bundle) msg.obj);
1419                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1420                     break;
1421                 case UPDATE_PACKAGE_COMPATIBILITY_INFO:
1422                     handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
1423                     break;
1424                 case TRIM_MEMORY:
1425                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
1426                     handleTrimMemory(msg.arg1);
1427                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1428                     break;
1429                 case UNSTABLE_PROVIDER_DIED:
1430                     handleUnstableProviderDied((IBinder)msg.obj, false);
1431                     break;
1432             }
1433             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
1434         }
1435
1436         private void maybeSnapshot() {
1437             if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) {
1438                 // convert the *private* ActivityThread.PackageInfo to *public* known
1439                 // android.content.pm.PackageInfo
1440                 String packageName = mBoundApplication.info.mPackageName;
1441                 android.content.pm.PackageInfo packageInfo = null;
1442                 try {
1443                     Context context = getSystemContext();
1444                     if(context == null) {
1445                         Log.e(TAG, "cannot get a valid context");
1446                         return;
1447                     }
1448                     PackageManager pm = context.getPackageManager();
1449                     if(pm == null) {
1450                         Log.e(TAG, "cannot get a valid PackageManager");
1451                         return;
1452                     }
1453                     packageInfo = pm.getPackageInfo(
1454                             packageName, PackageManager.GET_ACTIVITIES);
1455                 } catch (NameNotFoundException e) {
1456                     Log.e(TAG, "cannot get package info for " + packageName, e);
1457                 }
1458                 SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo);
1459             }
1460         }
1461     }
1462
1463     private class Idler implements MessageQueue.IdleHandler {
1464         public final boolean queueIdle() {
1465             ActivityClientRecord a = mNewActivities;
1466             boolean stopProfiling = false;
1467             if (mBoundApplication != null && mProfiler.profileFd != null
1468                     && mProfiler.autoStopProfiler) {
1469                 stopProfiling = true;
1470             }
1471             if (a != null) {
1472                 mNewActivities = null;
1473                 IActivityManager am = ActivityManagerNative.getDefault();
1474                 ActivityClientRecord prev;
1475                 do {
1476                     if (localLOGV) Slog.v(
1477                         TAG, "Reporting idle of " + a +
1478                         " finished=" +
1479                         (a.activity != null && a.activity.mFinished));
1480                     if (a.activity != null && !a.activity.mFinished) {
1481                         try {
1482                             am.activityIdle(a.token, a.createdConfig, stopProfiling);
1483                             a.createdConfig = null;
1484                         } catch (RemoteException ex) {
1485                             // Ignore
1486                         }
1487                     }
1488                     prev = a;
1489                     a = a.nextIdle;
1490                     prev.nextIdle = null;
1491                 } while (a != null);
1492             }
1493             if (stopProfiling) {
1494                 mProfiler.stopProfiling();
1495             }
1496             ensureJitEnabled();
1497             return false;
1498         }
1499     }
1500
1501     final class GcIdler implements MessageQueue.IdleHandler {
1502         public final boolean queueIdle() {
1503             doGcIfNeeded();
1504             return false;
1505         }
1506     }
1507
1508     private static class ResourcesKey {
1509         final private String mResDir;
1510         final private int mDisplayId;
1511         final private Configuration mOverrideConfiguration;
1512         final private float mScale;
1513         final private int mHash;
1514
1515         ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale) {
1516             mResDir = resDir;
1517             mDisplayId = displayId;
1518             if (overrideConfiguration != null) {
1519                 if (Configuration.EMPTY.equals(overrideConfiguration)) {
1520                     overrideConfiguration = null;
1521                 }
1522             }
1523             mOverrideConfiguration = overrideConfiguration;
1524             mScale = scale;
1525             int hash = 17;
1526             hash = 31 * hash + mResDir.hashCode();
1527             hash = 31 * hash + mDisplayId;
1528             hash = 31 * hash + (mOverrideConfiguration != null
1529                     ? mOverrideConfiguration.hashCode() : 0);
1530             hash = 31 * hash + Float.floatToIntBits(mScale);
1531             mHash = hash;
1532         }
1533
1534         @Override
1535         public int hashCode() {
1536             return mHash;
1537         }
1538
1539         @Override
1540         public boolean equals(Object obj) {
1541             if (!(obj instanceof ResourcesKey)) {
1542                 return false;
1543             }
1544             ResourcesKey peer = (ResourcesKey) obj;
1545             if (!mResDir.equals(peer.mResDir)) {
1546                 return false;
1547             }
1548             if (mDisplayId != peer.mDisplayId) {
1549                 return false;
1550             }
1551             if (mOverrideConfiguration != peer.mOverrideConfiguration) {
1552                 if (mOverrideConfiguration == null || peer.mOverrideConfiguration == null) {
1553                     return false;
1554                 }
1555                 if (!mOverrideConfiguration.equals(peer.mOverrideConfiguration)) {
1556                     return false;
1557                 }
1558             }
1559             if (mScale != peer.mScale) {
1560                 return false;
1561             }
1562             return true;
1563         }
1564     }
1565
1566     public static ActivityThread currentActivityThread() {
1567         return sThreadLocal.get();
1568     }
1569
1570     public static String currentPackageName() {
1571         ActivityThread am = currentActivityThread();
1572         return (am != null && am.mBoundApplication != null)
1573             ? am.mBoundApplication.processName : null;
1574     }
1575
1576     public static Application currentApplication() {
1577         ActivityThread am = currentActivityThread();
1578         return am != null ? am.mInitialApplication : null;
1579     }
1580
1581     public static IPackageManager getPackageManager() {
1582         if (sPackageManager != null) {
1583             //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
1584             return sPackageManager;
1585         }
1586         IBinder b = ServiceManager.getService("package");
1587         //Slog.v("PackageManager", "default service binder = " + b);
1588         sPackageManager = IPackageManager.Stub.asInterface(b);
1589         //Slog.v("PackageManager", "default service = " + sPackageManager);
1590         return sPackageManager;
1591     }
1592
1593     private void flushDisplayMetricsLocked() {
1594         mDefaultDisplayMetrics.clear();
1595     }
1596
1597     DisplayMetrics getDisplayMetricsLocked(int displayId, CompatibilityInfo ci) {
1598         boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
1599         DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(ci) : null;
1600         if (dm != null) {
1601             return dm;
1602         }
1603         dm = new DisplayMetrics();
1604
1605         DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
1606         if (displayManager == null) {
1607             // may be null early in system startup
1608             dm.setToDefaults();
1609             return dm;
1610         }
1611
1612         if (isDefaultDisplay) {
1613             mDefaultDisplayMetrics.put(ci, dm);
1614         }
1615
1616         CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
1617         cih.set(ci);
1618         Display d = displayManager.getCompatibleDisplay(displayId, cih);
1619         if (d != null) {
1620             d.getMetrics(dm);
1621         } else {
1622             // Display no longer exists
1623             // FIXME: This would not be a problem if we kept the Display object around
1624             // instead of using the raw display id everywhere.  The Display object caches
1625             // its information even after the display has been removed.
1626             dm.setToDefaults();
1627         }
1628         //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
1629         //        + metrics.heightPixels + " den=" + metrics.density
1630         //        + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
1631         return dm;
1632     }
1633
1634     private Configuration mMainThreadConfig = new Configuration();
1635     Configuration applyConfigCompatMainThread(int displayDensity, Configuration config,
1636             CompatibilityInfo compat) {
1637         if (config == null) {
1638             return null;
1639         }
1640         if (compat != null && !compat.supportsScreen()) {
1641             mMainThreadConfig.setTo(config);
1642             config = mMainThreadConfig;
1643             compat.applyToConfiguration(displayDensity, config);
1644         }
1645         return config;
1646     }
1647
1648     /**
1649      * Creates the top level Resources for applications with the given compatibility info.
1650      *
1651      * @param resDir the resource directory.
1652      * @param compInfo the compability info. It will use the default compatibility info when it's
1653      * null.
1654      */
1655     Resources getTopLevelResources(String resDir,
1656             int displayId, Configuration overrideConfiguration,
1657             CompatibilityInfo compInfo) {
1658         ResourcesKey key = new ResourcesKey(resDir,
1659                 displayId, overrideConfiguration,
1660                 compInfo.applicationScale);
1661         Resources r;
1662         synchronized (mPackages) {
1663             // Resources is app scale dependent.
1664             if (false) {
1665                 Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
1666                         + compInfo.applicationScale);
1667             }
1668             WeakReference<Resources> wr = mActiveResources.get(key);
1669             r = wr != null ? wr.get() : null;
1670             //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
1671             if (r != null && r.getAssets().isUpToDate()) {
1672                 if (false) {
1673                     Slog.w(TAG, "Returning cached resources " + r + " " + resDir
1674                             + ": appScale=" + r.getCompatibilityInfo().applicationScale);
1675                 }
1676                 return r;
1677             }
1678         }
1679
1680         //if (r != null) {
1681         //    Slog.w(TAG, "Throwing away out-of-date resources!!!! "
1682         //            + r + " " + resDir);
1683         //}
1684
1685         AssetManager assets = new AssetManager();
1686         if (assets.addAssetPath(resDir) == 0) {
1687             return null;
1688         }
1689
1690         //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
1691         DisplayMetrics dm = getDisplayMetricsLocked(displayId, null);
1692         Configuration config;
1693         boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
1694         if (!isDefaultDisplay || key.mOverrideConfiguration != null) {
1695             config = new Configuration(getConfiguration());
1696             if (!isDefaultDisplay) {
1697                 applyNonDefaultDisplayMetricsToConfigurationLocked(dm, config);
1698             }
1699             if (key.mOverrideConfiguration != null) {
1700                 config.updateFrom(key.mOverrideConfiguration);
1701             }
1702         } else {
1703             config = getConfiguration();
1704         }
1705         r = new Resources(assets, dm, config, compInfo);
1706         if (false) {
1707             Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
1708                     + r.getConfiguration() + " appScale="
1709                     + r.getCompatibilityInfo().applicationScale);
1710         }
1711
1712         synchronized (mPackages) {
1713             WeakReference<Resources> wr = mActiveResources.get(key);
1714             Resources existing = wr != null ? wr.get() : null;
1715             if (existing != null && existing.getAssets().isUpToDate()) {
1716                 // Someone else already created the resources while we were
1717                 // unlocked; go ahead and use theirs.
1718                 r.getAssets().close();
1719                 return existing;
1720             }
1721             
1722             // XXX need to remove entries when weak references go away
1723             mActiveResources.put(key, new WeakReference<Resources>(r));
1724             return r;
1725         }
1726     }
1727
1728     /**
1729      * Creates the top level resources for the given package.
1730      */
1731     Resources getTopLevelResources(String resDir,
1732             int displayId, Configuration overrideConfiguration,
1733             LoadedApk pkgInfo) {
1734         return getTopLevelResources(resDir, displayId, overrideConfiguration,
1735                 pkgInfo.mCompatibilityInfo.get());
1736     }
1737
1738     final Handler getHandler() {
1739         return mH;
1740     }
1741
1742     public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
1743             int flags) {
1744         return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());
1745     }
1746
1747     public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
1748             int flags, int userId) {
1749         synchronized (mPackages) {
1750             WeakReference<LoadedApk> ref;
1751             if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
1752                 ref = mPackages.get(packageName);
1753             } else {
1754                 ref = mResourcePackages.get(packageName);
1755             }
1756             LoadedApk packageInfo = ref != null ? ref.get() : null;
1757             //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
1758             //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
1759             //        + ": " + packageInfo.mResources.getAssets().isUpToDate());
1760             if (packageInfo != null && (packageInfo.mResources == null
1761                     || packageInfo.mResources.getAssets().isUpToDate())) {
1762                 if (packageInfo.isSecurityViolation()
1763                         && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
1764                     throw new SecurityException(
1765                             "Requesting code from " + packageName
1766                             + " to be run in process "
1767                             + mBoundApplication.processName
1768                             + "/" + mBoundApplication.appInfo.uid);
1769                 }
1770                 return packageInfo;
1771             }
1772         }
1773
1774         ApplicationInfo ai = null;
1775         try {
1776             ai = getPackageManager().getApplicationInfo(packageName,
1777                     PackageManager.GET_SHARED_LIBRARY_FILES, userId);
1778         } catch (RemoteException e) {
1779             // Ignore
1780         }
1781
1782         if (ai != null) {
1783             return getPackageInfo(ai, compatInfo, flags);
1784         }
1785
1786         return null;
1787     }
1788
1789     public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
1790             int flags) {
1791         boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
1792         boolean securityViolation = includeCode && ai.uid != 0
1793                 && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
1794                         ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
1795                         : true);
1796         if ((flags&(Context.CONTEXT_INCLUDE_CODE
1797                 |Context.CONTEXT_IGNORE_SECURITY))
1798                 == Context.CONTEXT_INCLUDE_CODE) {
1799             if (securityViolation) {
1800                 String msg = "Requesting code from " + ai.packageName
1801                         + " (with uid " + ai.uid + ")";
1802                 if (mBoundApplication != null) {
1803                     msg = msg + " to be run in process "
1804                         + mBoundApplication.processName + " (with uid "
1805                         + mBoundApplication.appInfo.uid + ")";
1806                 }
1807                 throw new SecurityException(msg);
1808             }
1809         }
1810         return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode);
1811     }
1812
1813     public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
1814             CompatibilityInfo compatInfo) {
1815         return getPackageInfo(ai, compatInfo, null, false, true);
1816     }
1817
1818     public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
1819         synchronized (mPackages) {
1820             WeakReference<LoadedApk> ref;
1821             if (includeCode) {
1822                 ref = mPackages.get(packageName);
1823             } else {
1824                 ref = mResourcePackages.get(packageName);
1825             }
1826             return ref != null ? ref.get() : null;
1827         }
1828     }
1829
1830     private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
1831             ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
1832         synchronized (mPackages) {
1833             WeakReference<LoadedApk> ref;
1834             if (includeCode) {
1835                 ref = mPackages.get(aInfo.packageName);
1836             } else {
1837                 ref = mResourcePackages.get(aInfo.packageName);
1838             }
1839             LoadedApk packageInfo = ref != null ? ref.get() : null;
1840             if (packageInfo == null || (packageInfo.mResources != null
1841                     && !packageInfo.mResources.getAssets().isUpToDate())) {
1842                 if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
1843                         : "Loading resource-only package ") + aInfo.packageName
1844                         + " (in " + (mBoundApplication != null
1845                                 ? mBoundApplication.processName : null)
1846                         + ")");
1847                 packageInfo =
1848                     new LoadedApk(this, aInfo, compatInfo, this, baseLoader,
1849                             securityViolation, includeCode &&
1850                             (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
1851                 if (includeCode) {
1852                     mPackages.put(aInfo.packageName,
1853                             new WeakReference<LoadedApk>(packageInfo));
1854                 } else {
1855                     mResourcePackages.put(aInfo.packageName,
1856                             new WeakReference<LoadedApk>(packageInfo));
1857                 }
1858             }
1859             return packageInfo;
1860         }
1861     }
1862
1863     ActivityThread() {
1864     }
1865
1866     public ApplicationThread getApplicationThread()
1867     {
1868         return mAppThread;
1869     }
1870
1871     public Instrumentation getInstrumentation()
1872     {
1873         return mInstrumentation;
1874     }
1875
1876     public Configuration getConfiguration() {
1877         return mResConfiguration;
1878     }
1879
1880     public boolean isProfiling() {
1881         return mProfiler != null && mProfiler.profileFile != null
1882                 && mProfiler.profileFd == null;
1883     }
1884
1885     public String getProfileFilePath() {
1886         return mProfiler.profileFile;
1887     }
1888
1889     public Looper getLooper() {
1890         return mLooper;
1891     }
1892
1893     public Application getApplication() {
1894         return mInitialApplication;
1895     }
1896
1897     public String getProcessName() {
1898         return mBoundApplication.processName;
1899     }
1900
1901     public ContextImpl getSystemContext() {
1902         synchronized (this) {
1903             if (mSystemContext == null) {
1904                 ContextImpl context =
1905                     ContextImpl.createSystemContext(this);
1906                 LoadedApk info = new LoadedApk(this, "android", context, null,
1907                         CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
1908                 context.init(info, null, this);
1909                 context.getResources().updateConfiguration(
1910                         getConfiguration(), getDisplayMetricsLocked(
1911                                 Display.DEFAULT_DISPLAY,
1912                                 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO));
1913                 mSystemContext = context;
1914                 //Slog.i(TAG, "Created system resources " + context.getResources()
1915                 //        + ": " + context.getResources().getConfiguration());
1916             }
1917         }
1918         return mSystemContext;
1919     }
1920
1921     public void installSystemApplicationInfo(ApplicationInfo info) {
1922         synchronized (this) {
1923             ContextImpl context = getSystemContext();
1924             context.init(new LoadedApk(this, "android", context, info,
1925                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this);
1926
1927             // give ourselves a default profiler
1928             mProfiler = new Profiler();
1929         }
1930     }
1931
1932     void ensureJitEnabled() {
1933         if (!mJitEnabled) {
1934             mJitEnabled = true;
1935             dalvik.system.VMRuntime.getRuntime().startJitCompilation();
1936         }
1937     }
1938     
1939     void scheduleGcIdler() {
1940         if (!mGcIdlerScheduled) {
1941             mGcIdlerScheduled = true;
1942             Looper.myQueue().addIdleHandler(mGcIdler);
1943         }
1944         mH.removeMessages(H.GC_WHEN_IDLE);
1945     }
1946
1947     void unscheduleGcIdler() {
1948         if (mGcIdlerScheduled) {
1949             mGcIdlerScheduled = false;
1950             Looper.myQueue().removeIdleHandler(mGcIdler);
1951         }
1952         mH.removeMessages(H.GC_WHEN_IDLE);
1953     }
1954
1955     void doGcIfNeeded() {
1956         mGcIdlerScheduled = false;
1957         final long now = SystemClock.uptimeMillis();
1958         //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
1959         //        + "m now=" + now);
1960         if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
1961             //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
1962             BinderInternal.forceGc("bg");
1963         }
1964     }
1965
1966     public void registerOnActivityPausedListener(Activity activity,
1967             OnActivityPausedListener listener) {
1968         synchronized (mOnPauseListeners) {
1969             ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
1970             if (list == null) {
1971                 list = new ArrayList<OnActivityPausedListener>();
1972                 mOnPauseListeners.put(activity, list);
1973             }
1974             list.add(listener);
1975         }
1976     }
1977
1978     public void unregisterOnActivityPausedListener(Activity activity,
1979             OnActivityPausedListener listener) {
1980         synchronized (mOnPauseListeners) {
1981             ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
1982             if (list != null) {
1983                 list.remove(listener);
1984             }
1985         }
1986     }
1987
1988     public final ActivityInfo resolveActivityInfo(Intent intent) {
1989         ActivityInfo aInfo = intent.resolveActivityInfo(
1990                 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
1991         if (aInfo == null) {
1992             // Throw an exception.
1993             Instrumentation.checkStartActivityResult(
1994                     ActivityManager.START_CLASS_NOT_FOUND, intent);
1995         }
1996         return aInfo;
1997     }
1998
1999     public final Activity startActivityNow(Activity parent, String id,
2000         Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
2001         Activity.NonConfigurationInstances lastNonConfigurationInstances) {
2002         ActivityClientRecord r = new ActivityClientRecord();
2003             r.token = token;
2004             r.ident = 0;
2005             r.intent = intent;
2006             r.state = state;
2007             r.parent = parent;
2008             r.embeddedID = id;
2009             r.activityInfo = activityInfo;
2010             r.lastNonConfigurationInstances = lastNonConfigurationInstances;
2011         if (localLOGV) {
2012             ComponentName compname = intent.getComponent();
2013             String name;
2014             if (compname != null) {
2015                 name = compname.toShortString();
2016             } else {
2017                 name = "(Intent " + intent + ").getComponent() returned null";
2018             }
2019             Slog.v(TAG, "Performing launch: action=" + intent.getAction()
2020                     + ", comp=" + name
2021                     + ", token=" + token);
2022         }
2023         return performLaunchActivity(r, null);
2024     }
2025
2026     public final Activity getActivity(IBinder token) {
2027         return mActivities.get(token).activity;
2028     }
2029
2030     public final void sendActivityResult(
2031             IBinder token, String id, int requestCode,
2032             int resultCode, Intent data) {
2033         if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
2034                 + " req=" + requestCode + " res=" + resultCode + " data=" + data);
2035         ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2036         list.add(new ResultInfo(id, requestCode, resultCode, data));
2037         mAppThread.scheduleSendResult(token, list);
2038     }
2039
2040     // if the thread hasn't started yet, we don't have the handler, so just
2041     // save the messages until we're ready.
2042     private void queueOrSendMessage(int what, Object obj) {
2043         queueOrSendMessage(what, obj, 0, 0);
2044     }
2045
2046     private void queueOrSendMessage(int what, Object obj, int arg1) {
2047         queueOrSendMessage(what, obj, arg1, 0);
2048     }
2049
2050     private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
2051         synchronized (this) {
2052             if (DEBUG_MESSAGES) Slog.v(
2053                 TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
2054                 + ": " + arg1 + " / " + obj);
2055             Message msg = Message.obtain();
2056             msg.what = what;
2057             msg.obj = obj;
2058             msg.arg1 = arg1;
2059             msg.arg2 = arg2;
2060             mH.sendMessage(msg);
2061         }
2062     }
2063
2064     final void scheduleContextCleanup(ContextImpl context, String who,
2065             String what) {
2066         ContextCleanupInfo cci = new ContextCleanupInfo();
2067         cci.context = context;
2068         cci.who = who;
2069         cci.what = what;
2070         queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
2071     }
2072
2073     private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
2074         // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
2075
2076         ActivityInfo aInfo = r.activityInfo;
2077         if (r.packageInfo == null) {
2078             r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
2079                     Context.CONTEXT_INCLUDE_CODE);
2080         }
2081
2082         ComponentName component = r.intent.getComponent();
2083         if (component == null) {
2084             component = r.intent.resolveActivity(
2085                 mInitialApplication.getPackageManager());
2086             r.intent.setComponent(component);
2087         }
2088
2089         if (r.activityInfo.targetActivity != null) {
2090             component = new ComponentName(r.activityInfo.packageName,
2091                     r.activityInfo.targetActivity);
2092         }
2093
2094         Activity activity = null;
2095         try {
2096             java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
2097             activity = mInstrumentation.newActivity(
2098                     cl, component.getClassName(), r.intent);
2099             StrictMode.incrementExpectedActivityCount(activity.getClass());
2100             r.intent.setExtrasClassLoader(cl);
2101             if (r.state != null) {
2102                 r.state.setClassLoader(cl);
2103             }
2104         } catch (Exception e) {
2105             if (!mInstrumentation.onException(activity, e)) {
2106                 throw new RuntimeException(
2107                     "Unable to instantiate activity " + component
2108                     + ": " + e.toString(), e);
2109             }
2110         }
2111
2112         try {
2113             Application app = r.packageInfo.makeApplication(false, mInstrumentation);
2114
2115             if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
2116             if (localLOGV) Slog.v(
2117                     TAG, r + ": app=" + app
2118                     + ", appName=" + app.getPackageName()
2119                     + ", pkg=" + r.packageInfo.getPackageName()
2120                     + ", comp=" + r.intent.getComponent().toShortString()
2121                     + ", dir=" + r.packageInfo.getAppDir());
2122
2123             if (activity != null) {
2124                 Context appContext = createBaseContextForActivity(r, activity);
2125                 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
2126                 Configuration config = new Configuration(mCompatConfiguration);
2127                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
2128                         + r.activityInfo.name + " with config " + config);
2129                 activity.attach(appContext, this, getInstrumentation(), r.token,
2130                         r.ident, app, r.intent, r.activityInfo, title, r.parent,
2131                         r.embeddedID, r.lastNonConfigurationInstances, config);
2132
2133                 if (customIntent != null) {
2134                     activity.mIntent = customIntent;
2135                 }
2136                 r.lastNonConfigurationInstances = null;
2137                 activity.mStartedActivity = false;
2138                 int theme = r.activityInfo.getThemeResource();
2139                 if (theme != 0) {
2140                     activity.setTheme(theme);
2141                 }
2142
2143                 activity.mCalled = false;
2144                 mInstrumentation.callActivityOnCreate(activity, r.state);
2145                 if (!activity.mCalled) {
2146                     throw new SuperNotCalledException(
2147                         "Activity " + r.intent.getComponent().toShortString() +
2148                         " did not call through to super.onCreate()");
2149                 }
2150                 r.activity = activity;
2151                 r.stopped = true;
2152                 if (!r.activity.mFinished) {
2153                     activity.performStart();
2154                     r.stopped = false;
2155                 }
2156                 if (!r.activity.mFinished) {
2157                     if (r.state != null) {
2158                         mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
2159                     }
2160                 }
2161                 if (!r.activity.mFinished) {
2162                     activity.mCalled = false;
2163                     mInstrumentation.callActivityOnPostCreate(activity, r.state);
2164                     if (!activity.mCalled) {
2165                         throw new SuperNotCalledException(
2166                             "Activity " + r.intent.getComponent().toShortString() +
2167                             " did not call through to super.onPostCreate()");
2168                     }
2169                 }
2170             }
2171             r.paused = true;
2172
2173             mActivities.put(r.token, r);
2174
2175         } catch (SuperNotCalledException e) {
2176             throw e;
2177
2178         } catch (Exception e) {
2179             if (!mInstrumentation.onException(activity, e)) {
2180                 throw new RuntimeException(
2181                     "Unable to start activity " + component
2182                     + ": " + e.toString(), e);
2183             }
2184         }
2185
2186         return activity;
2187     }
2188
2189     private Context createBaseContextForActivity(ActivityClientRecord r,
2190             final Activity activity) {
2191         ContextImpl appContext = new ContextImpl();
2192         appContext.init(r.packageInfo, r.token, this);
2193         appContext.setOuterContext(activity);
2194
2195         // For debugging purposes, if the activity's package name contains the value of
2196         // the "debug.use-second-display" system property as a substring, then show
2197         // its content on a secondary display if there is one.
2198         Context baseContext = appContext;
2199         String pkgName = SystemProperties.get("debug.second-display.pkg");
2200         if (pkgName != null && !pkgName.isEmpty()
2201                 && r.packageInfo.mPackageName.contains(pkgName)) {
2202             DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
2203             for (int displayId : dm.getDisplayIds()) {
2204                 if (displayId != Display.DEFAULT_DISPLAY) {
2205                     Display display = dm.getRealDisplay(displayId);
2206                     baseContext = appContext.createDisplayContext(display);
2207                     break;
2208                 }
2209             }
2210         }
2211         return baseContext;
2212     }
2213
2214     private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
2215         // If we are getting ready to gc after going to the background, well
2216         // we are back active so skip it.
2217         unscheduleGcIdler();
2218
2219         if (r.profileFd != null) {
2220             mProfiler.setProfiler(r.profileFile, r.profileFd);
2221             mProfiler.startProfiling();
2222             mProfiler.autoStopProfiler = r.autoStopProfiler;
2223         }
2224
2225         // Make sure we are running with the most recent config.
2226         handleConfigurationChanged(null, null);
2227
2228         if (localLOGV) Slog.v(
2229             TAG, "Handling launch of " + r);
2230         Activity a = performLaunchActivity(r, customIntent);
2231
2232         if (a != null) {
2233             r.createdConfig = new Configuration(mConfiguration);
2234             Bundle oldState = r.state;
2235             handleResumeActivity(r.token, false, r.isForward,
2236                     !r.activity.mFinished && !r.startsNotResumed);
2237
2238             if (!r.activity.mFinished && r.startsNotResumed) {
2239                 // The activity manager actually wants this one to start out
2240                 // paused, because it needs to be visible but isn't in the
2241                 // foreground.  We accomplish this by going through the
2242                 // normal startup (because activities expect to go through
2243                 // onResume() the first time they run, before their window
2244                 // is displayed), and then pausing it.  However, in this case
2245                 // we do -not- need to do the full pause cycle (of freezing
2246                 // and such) because the activity manager assumes it can just
2247                 // retain the current state it has.
2248                 try {
2249                     r.activity.mCalled = false;
2250                     mInstrumentation.callActivityOnPause(r.activity);
2251                     // We need to keep around the original state, in case
2252                     // we need to be created again.  But we only do this
2253                     // for pre-Honeycomb apps, which always save their state
2254                     // when pausing, so we can not have them save their state
2255                     // when restarting from a paused state.  For HC and later,
2256                     // we want to (and can) let the state be saved as the normal
2257                     // part of stopping the activity.
2258                     if (r.isPreHoneycomb()) {
2259                         r.state = oldState;
2260                     }
2261                     if (!r.activity.mCalled) {
2262                         throw new SuperNotCalledException(
2263                             "Activity " + r.intent.getComponent().toShortString() +
2264                             " did not call through to super.onPause()");
2265                     }
2266
2267                 } catch (SuperNotCalledException e) {
2268                     throw e;
2269
2270                 } catch (Exception e) {
2271                     if (!mInstrumentation.onException(r.activity, e)) {
2272                         throw new RuntimeException(
2273                                 "Unable to pause activity "
2274                                 + r.intent.getComponent().toShortString()
2275                                 + ": " + e.toString(), e);
2276                     }
2277                 }
2278                 r.paused = true;
2279             }
2280         } else {
2281             // If there was an error, for any reason, tell the activity
2282             // manager to stop us.
2283             try {
2284                 ActivityManagerNative.getDefault()
2285                     .finishActivity(r.token, Activity.RESULT_CANCELED, null);
2286             } catch (RemoteException ex) {
2287                 // Ignore
2288             }
2289         }
2290     }
2291
2292     private void deliverNewIntents(ActivityClientRecord r,
2293             List<Intent> intents) {
2294         final int N = intents.size();
2295         for (int i=0; i<N; i++) {
2296             Intent intent = intents.get(i);
2297             intent.setExtrasClassLoader(r.activity.getClassLoader());
2298             r.activity.mFragments.noteStateNotSaved();
2299             mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2300         }
2301     }
2302
2303     public final void performNewIntents(IBinder token,
2304             List<Intent> intents) {
2305         ActivityClientRecord r = mActivities.get(token);
2306         if (r != null) {
2307             final boolean resumed = !r.paused;
2308             if (resumed) {
2309                 r.activity.mTemporaryPause = true;
2310                 mInstrumentation.callActivityOnPause(r.activity);
2311             }
2312             deliverNewIntents(r, intents);
2313             if (resumed) {
2314                 r.activity.performResume();
2315                 r.activity.mTemporaryPause = false;
2316             }
2317         }
2318     }
2319
2320     private void handleNewIntent(NewIntentData data) {
2321         performNewIntents(data.token, data.intents);
2322     }
2323
2324     private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
2325
2326     /**
2327      * Return the Intent that's currently being handled by a
2328      * BroadcastReceiver on this thread, or null if none.
2329      * @hide
2330      */
2331     public static Intent getIntentBeingBroadcast() {
2332         return sCurrentBroadcastIntent.get();
2333     }
2334
2335     private void handleReceiver(ReceiverData data) {
2336         // If we are getting ready to gc after going to the background, well
2337         // we are back active so skip it.
2338         unscheduleGcIdler();
2339
2340         String component = data.intent.getComponent().getClassName();
2341
2342         LoadedApk packageInfo = getPackageInfoNoCheck(
2343                 data.info.applicationInfo, data.compatInfo);
2344
2345         IActivityManager mgr = ActivityManagerNative.getDefault();
2346
2347         BroadcastReceiver receiver;
2348         try {
2349             java.lang.ClassLoader cl = packageInfo.getClassLoader();
2350             data.intent.setExtrasClassLoader(cl);
2351             data.setExtrasClassLoader(cl);
2352             receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2353         } catch (Exception e) {
2354             if (DEBUG_BROADCAST) Slog.i(TAG,
2355                     "Finishing failed broadcast to " + data.intent.getComponent());
2356             data.sendFinished(mgr);
2357             throw new RuntimeException(
2358                 "Unable to instantiate receiver " + component
2359                 + ": " + e.toString(), e);
2360         }
2361
2362         try {
2363             Application app = packageInfo.makeApplication(false, mInstrumentation);
2364
2365             if (localLOGV) Slog.v(
2366                 TAG, "Performing receive of " + data.intent
2367                 + ": app=" + app
2368                 + ", appName=" + app.getPackageName()
2369                 + ", pkg=" + packageInfo.getPackageName()
2370                 + ", comp=" + data.intent.getComponent().toShortString()
2371                 + ", dir=" + packageInfo.getAppDir());
2372
2373             ContextImpl context = (ContextImpl)app.getBaseContext();
2374             sCurrentBroadcastIntent.set(data.intent);
2375             receiver.setPendingResult(data);
2376             receiver.onReceive(context.getReceiverRestrictedContext(),
2377                     data.intent);
2378         } catch (Exception e) {
2379             if (DEBUG_BROADCAST) Slog.i(TAG,
2380                     "Finishing failed broadcast to " + data.intent.getComponent());
2381             data.sendFinished(mgr);
2382             if (!mInstrumentation.onException(receiver, e)) {
2383                 throw new RuntimeException(
2384                     "Unable to start receiver " + component
2385                     + ": " + e.toString(), e);
2386             }
2387         } finally {
2388             sCurrentBroadcastIntent.set(null);
2389         }
2390
2391         if (receiver.getPendingResult() != null) {
2392             data.finish();
2393         }
2394     }
2395
2396     // Instantiate a BackupAgent and tell it that it's alive
2397     private void handleCreateBackupAgent(CreateBackupAgentData data) {
2398         if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
2399
2400         // Sanity check the requested target package's uid against ours
2401         try {
2402             PackageInfo requestedPackage = getPackageManager().getPackageInfo(
2403                     data.appInfo.packageName, 0, UserHandle.myUserId());
2404             if (requestedPackage.applicationInfo.uid != Process.myUid()) {
2405                 Slog.w(TAG, "Asked to instantiate non-matching package "
2406                         + data.appInfo.packageName);
2407                 return;
2408             }
2409         } catch (RemoteException e) {
2410             Slog.e(TAG, "Can't reach package manager", e);
2411             return;
2412         }
2413
2414         // no longer idle; we have backup work to do
2415         unscheduleGcIdler();
2416
2417         // instantiate the BackupAgent class named in the manifest
2418         LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
2419         String packageName = packageInfo.mPackageName;
2420         if (packageName == null) {
2421             Slog.d(TAG, "Asked to create backup agent for nonexistent package");
2422             return;
2423         }
2424
2425         if (mBackupAgents.get(packageName) != null) {
2426             Slog.d(TAG, "BackupAgent " + "  for " + packageName
2427                     + " already exists");
2428             return;
2429         }
2430
2431         BackupAgent agent = null;
2432         String classname = data.appInfo.backupAgentName;
2433
2434         // full backup operation but no app-supplied agent?  use the default implementation
2435         if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
2436                 || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) {
2437             classname = "android.app.backup.FullBackupAgent";
2438         }
2439
2440         try {
2441             IBinder binder = null;
2442             try {
2443                 if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
2444
2445                 java.lang.ClassLoader cl = packageInfo.getClassLoader();
2446                 agent = (BackupAgent) cl.loadClass(classname).newInstance();
2447
2448                 // set up the agent's context
2449                 ContextImpl context = new ContextImpl();
2450                 context.init(packageInfo, null, this);
2451                 context.setOuterContext(agent);
2452                 agent.attach(context);
2453
2454                 agent.onCreate();
2455                 binder = agent.onBind();
2456                 mBackupAgents.put(packageName, agent);
2457             } catch (Exception e) {
2458                 // If this is during restore, fail silently; otherwise go
2459                 // ahead and let the user see the crash.
2460                 Slog.e(TAG, "Agent threw during creation: " + e);
2461                 if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE
2462                         && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) {
2463                     throw e;
2464                 }
2465                 // falling through with 'binder' still null
2466             }
2467
2468             // tell the OS that we're live now
2469             try {
2470                 ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
2471             } catch (RemoteException e) {
2472                 // nothing to do.
2473             }
2474         } catch (Exception e) {
2475             throw new RuntimeException("Unable to create BackupAgent "
2476                     + classname + ": " + e.toString(), e);
2477         }
2478     }
2479
2480     // Tear down a BackupAgent
2481     private void handleDestroyBackupAgent(CreateBackupAgentData data) {
2482         if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
2483
2484         LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
2485         String packageName = packageInfo.mPackageName;
2486         BackupAgent agent = mBackupAgents.get(packageName);
2487         if (agent != null) {
2488             try {
2489                 agent.onDestroy();
2490             } catch (Exception e) {
2491                 Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
2492                 e.printStackTrace();
2493             }
2494             mBackupAgents.remove(packageName);
2495         } else {
2496             Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
2497         }
2498     }
2499
2500     private void handleCreateService(CreateServiceData data) {
2501         // If we are getting ready to gc after going to the background, well
2502         // we are back active so skip it.
2503         unscheduleGcIdler();
2504
2505         LoadedApk packageInfo = getPackageInfoNoCheck(
2506                 data.info.applicationInfo, data.compatInfo);
2507         Service service = null;
2508         try {
2509             java.lang.ClassLoader cl = packageInfo.getClassLoader();
2510             service = (Service) cl.loadClass(data.info.name).newInstance();
2511         } catch (Exception e) {
2512             if (!mInstrumentation.onException(service, e)) {
2513                 throw new RuntimeException(
2514                     "Unable to instantiate service " + data.info.name
2515                     + ": " + e.toString(), e);
2516             }
2517         }
2518
2519         try {
2520             if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
2521
2522             ContextImpl context = new ContextImpl();
2523             context.init(packageInfo, null, this);
2524
2525             Application app = packageInfo.makeApplication(false, mInstrumentation);
2526             context.setOuterContext(service);
2527             service.attach(context, this, data.info.name, data.token, app,
2528                     ActivityManagerNative.getDefault());
2529             service.onCreate();
2530             mServices.put(data.token, service);
2531             try {
2532                 ActivityManagerNative.getDefault().serviceDoneExecuting(
2533                         data.token, 0, 0, 0);
2534             } catch (RemoteException e) {
2535                 // nothing to do.
2536             }
2537         } catch (Exception e) {
2538             if (!mInstrumentation.onException(service, e)) {
2539                 throw new RuntimeException(
2540                     "Unable to create service " + data.info.name
2541                     + ": " + e.toString(), e);
2542             }
2543         }
2544     }
2545
2546     private void handleBindService(BindServiceData data) {
2547         Service s = mServices.get(data.token);
2548         if (DEBUG_SERVICE)
2549             Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
2550         if (s != null) {
2551             try {
2552                 data.intent.setExtrasClassLoader(s.getClassLoader());
2553                 try {
2554                     if (!data.rebind) {
2555                         IBinder binder = s.onBind(data.intent);
2556                         ActivityManagerNative.getDefault().publishService(
2557                                 data.token, data.intent, binder);
2558                     } else {
2559                         s.onRebind(data.intent);
2560                         ActivityManagerNative.getDefault().serviceDoneExecuting(
2561                                 data.token, 0, 0, 0);
2562                     }
2563                     ensureJitEnabled();
2564                 } catch (RemoteException ex) {
2565                 }
2566             } catch (Exception e) {
2567                 if (!mInstrumentation.onException(s, e)) {
2568                     throw new RuntimeException(
2569                             "Unable to bind to service " + s
2570                             + " with " + data.intent + ": " + e.toString(), e);
2571                 }
2572             }
2573         }
2574     }
2575
2576     private void handleUnbindService(BindServiceData data) {
2577         Service s = mServices.get(data.token);
2578         if (s != null) {
2579             try {
2580                 data.intent.setExtrasClassLoader(s.getClassLoader());
2581                 boolean doRebind = s.onUnbind(data.intent);
2582                 try {
2583                     if (doRebind) {
2584                         ActivityManagerNative.getDefault().unbindFinished(
2585                                 data.token, data.intent, doRebind);
2586                     } else {
2587                         ActivityManagerNative.getDefault().serviceDoneExecuting(
2588                                 data.token, 0, 0, 0);
2589                     }
2590                 } catch (RemoteException ex) {
2591                 }
2592             } catch (Exception e) {
2593                 if (!mInstrumentation.onException(s, e)) {
2594                     throw new RuntimeException(
2595                             "Unable to unbind to service " + s
2596                             + " with " + data.intent + ": " + e.toString(), e);
2597                 }
2598             }
2599         }
2600     }
2601
2602     private void handleDumpService(DumpComponentInfo info) {
2603         final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2604         try {
2605             Service s = mServices.get(info.token);
2606             if (s != null) {
2607                 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
2608                 s.dump(info.fd.getFileDescriptor(), pw, info.args);
2609                 pw.flush();
2610             }
2611         } finally {
2612             IoUtils.closeQuietly(info.fd);
2613             StrictMode.setThreadPolicy(oldPolicy);
2614         }
2615     }
2616
2617     private void handleDumpActivity(DumpComponentInfo info) {
2618         final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2619         try {
2620             ActivityClientRecord r = mActivities.get(info.token);
2621             if (r != null && r.activity != null) {
2622                 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
2623                 r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
2624                 pw.flush();
2625             }
2626         } finally {
2627             IoUtils.closeQuietly(info.fd);
2628             StrictMode.setThreadPolicy(oldPolicy);
2629         }
2630     }
2631
2632     private void handleDumpProvider(DumpComponentInfo info) {
2633         final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2634         try {
2635             ProviderClientRecord r = mLocalProviders.get(info.token);
2636             if (r != null && r.mLocalProvider != null) {
2637                 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
2638                 r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
2639                 pw.flush();
2640             }
2641         } finally {
2642             IoUtils.closeQuietly(info.fd);
2643             StrictMode.setThreadPolicy(oldPolicy);
2644         }
2645     }
2646
2647     private void handleServiceArgs(ServiceArgsData data) {
2648         Service s = mServices.get(data.token);
2649         if (s != null) {
2650             try {
2651                 if (data.args != null) {
2652                     data.args.setExtrasClassLoader(s.getClassLoader());
2653                 }
2654                 int res;
2655                 if (!data.taskRemoved) {
2656                     res = s.onStartCommand(data.args, data.flags, data.startId);
2657                 } else {
2658                     s.onTaskRemoved(data.args);
2659                     res = Service.START_TASK_REMOVED_COMPLETE;
2660                 }
2661
2662                 QueuedWork.waitToFinish();
2663
2664                 try {
2665                     ActivityManagerNative.getDefault().serviceDoneExecuting(
2666                             data.token, 1, data.startId, res);
2667                 } catch (RemoteException e) {
2668                     // nothing to do.
2669                 }
2670                 ensureJitEnabled();
2671             } catch (Exception e) {
2672                 if (!mInstrumentation.onException(s, e)) {
2673                     throw new RuntimeException(
2674                             "Unable to start service " + s
2675                             + " with " + data.args + ": " + e.toString(), e);
2676                 }
2677             }
2678         }
2679     }
2680
2681     private void handleStopService(IBinder token) {
2682         Service s = mServices.remove(token);
2683         if (s != null) {
2684             try {
2685                 if (localLOGV) Slog.v(TAG, "Destroying service " + s);
2686                 s.onDestroy();
2687                 Context context = s.getBaseContext();
2688                 if (context instanceof ContextImpl) {
2689                     final String who = s.getClassName();
2690                     ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
2691                 }
2692
2693                 QueuedWork.waitToFinish();
2694
2695                 try {
2696                     ActivityManagerNative.getDefault().serviceDoneExecuting(
2697                             token, 0, 0, 0);
2698                 } catch (RemoteException e) {
2699                     // nothing to do.
2700                 }
2701             } catch (Exception e) {
2702                 if (!mInstrumentation.onException(s, e)) {
2703                     throw new RuntimeException(
2704                             "Unable to stop service " + s
2705                             + ": " + e.toString(), e);
2706                 }
2707             }
2708         }
2709         //Slog.i(TAG, "Running services: " + mServices);
2710     }
2711
2712     public final ActivityClientRecord performResumeActivity(IBinder token,
2713             boolean clearHide) {
2714         ActivityClientRecord r = mActivities.get(token);
2715         if (localLOGV) Slog.v(TAG, "Performing resume of " + r
2716                 + " finished=" + r.activity.mFinished);
2717         if (r != null && !r.activity.mFinished) {
2718             if (clearHide) {
2719                 r.hideForNow = false;
2720                 r.activity.mStartedActivity = false;
2721             }
2722             try {
2723                 r.activity.mFragments.noteStateNotSaved();
2724                 if (r.pendingIntents != null) {
2725                     deliverNewIntents(r, r.pendingIntents);
2726                     r.pendingIntents = null;
2727                 }
2728                 if (r.pendingResults != null) {
2729                     deliverResults(r, r.pendingResults);
2730                     r.pendingResults = null;
2731                 }
2732                 r.activity.performResume();
2733
2734                 EventLog.writeEvent(LOG_ON_RESUME_CALLED,
2735                         UserHandle.myUserId(), r.activity.getComponentName().getClassName());
2736
2737                 r.paused = false;
2738                 r.stopped = false;
2739                 r.state = null;
2740             } catch (Exception e) {
2741                 if (!mInstrumentation.onException(r.activity, e)) {
2742                     throw new RuntimeException(
2743                         "Unable to resume activity "
2744                         + r.intent.getComponent().toShortString()
2745                         + ": " + e.toString(), e);
2746                 }
2747             }
2748         }
2749         return r;
2750     }
2751
2752     static final void cleanUpPendingRemoveWindows(ActivityClientRecord r) {
2753         if (r.mPendingRemoveWindow != null) {
2754             r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow);
2755             IBinder wtoken = r.mPendingRemoveWindow.getWindowToken();
2756             if (wtoken != null) {
2757                 WindowManagerGlobal.getInstance().closeAll(wtoken,
2758                         r.activity.getClass().getName(), "Activity");
2759             }
2760         }
2761         r.mPendingRemoveWindow = null;
2762         r.mPendingRemoveWindowManager = null;
2763     }
2764
2765     final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
2766             boolean reallyResume) {
2767         // If we are getting ready to gc after going to the background, well
2768         // we are back active so skip it.
2769         unscheduleGcIdler();
2770
2771         ActivityClientRecord r = performResumeActivity(token, clearHide);
2772
2773         if (r != null) {
2774             final Activity a = r.activity;
2775
2776             if (localLOGV) Slog.v(
2777                 TAG, "Resume " + r + " started activity: " +
2778                 a.mStartedActivity + ", hideForNow: " + r.hideForNow
2779                 + ", finished: " + a.mFinished);
2780
2781             final int forwardBit = isForward ?
2782                     WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
2783
2784             // If the window hasn't yet been added to the window manager,
2785             // and this guy didn't finish itself or start another activity,
2786             // then go ahead and add the window.
2787             boolean willBeVisible = !a.mStartedActivity;
2788             if (!willBeVisible) {
2789                 try {
2790                     willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
2791                             a.getActivityToken());
2792                 } catch (RemoteException e) {
2793                 }
2794             }
2795             if (r.window == null && !a.mFinished && willBeVisible) {
2796                 r.window = r.activity.getWindow();
2797                 View decor = r.window.getDecorView();
2798                 decor.setVisibility(View.INVISIBLE);
2799                 ViewManager wm = a.getWindowManager();
2800                 WindowManager.LayoutParams l = r.window.getAttributes();
2801                 a.mDecor = decor;
2802                 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2803                 l.softInputMode |= forwardBit;
2804                 if (a.mVisibleFromClient) {
2805                     a.mWindowAdded = true;
2806                     wm.addView(decor, l);
2807                 }
2808
2809             // If the window has already been added, but during resume
2810             // we started another activity, then don't yet make the
2811             // window visible.
2812             } else if (!willBeVisible) {
2813                 if (localLOGV) Slog.v(
2814                     TAG, "Launch " + r + " mStartedActivity set");
2815                 r.hideForNow = true;
2816             }
2817
2818             // Get rid of anything left hanging around.
2819             cleanUpPendingRemoveWindows(r);
2820
2821             // The window is now visible if it has been added, we are not
2822             // simply finishing, and we are not starting another activity.
2823             if (!r.activity.mFinished && willBeVisible
2824                     && r.activity.mDecor != null && !r.hideForNow) {
2825                 if (r.newConfig != null) {
2826                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
2827                             + r.activityInfo.name + " with newConfig " + r.newConfig);
2828                     performConfigurationChanged(r.activity, r.newConfig);
2829                     freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
2830                     r.newConfig = null;
2831                 }
2832                 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
2833                         + isForward);
2834                 WindowManager.LayoutParams l = r.window.getAttributes();
2835                 if ((l.softInputMode
2836                         & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
2837                         != forwardBit) {
2838                     l.softInputMode = (l.softInputMode
2839                             & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
2840                             | forwardBit;
2841                     if (r.activity.mVisibleFromClient) {
2842                         ViewManager wm = a.getWindowManager();
2843                         View decor = r.window.getDecorView();
2844                         wm.updateViewLayout(decor, l);
2845                     }
2846                 }
2847                 r.activity.mVisibleFromServer = true;
2848                 mNumVisibleActivities++;
2849                 if (r.activity.mVisibleFromClient) {
2850                     r.activity.makeVisible();
2851                 }
2852             }
2853
2854             if (!r.onlyLocalRequest) {
2855                 r.nextIdle = mNewActivities;
2856                 mNewActivities = r;
2857                 if (localLOGV) Slog.v(
2858                     TAG, "Scheduling idle handler for " + r);
2859                 Looper.myQueue().addIdleHandler(new Idler());
2860             }
2861             r.onlyLocalRequest = false;
2862
2863             // Tell the activity manager we have resumed.
2864             if (reallyResume) {
2865                 try {
2866                     ActivityManagerNative.getDefault().activityResumed(token);
2867                 } catch (RemoteException ex) {
2868                 }
2869             }
2870
2871         } else {
2872             // If an exception was thrown when trying to resume, then
2873             // just end this activity.
2874             try {
2875                 ActivityManagerNative.getDefault()
2876                     .finishActivity(token, Activity.RESULT_CANCELED, null);
2877             } catch (RemoteException ex) {
2878             }
2879         }
2880     }
2881
2882     private int mThumbnailWidth = -1;
2883     private int mThumbnailHeight = -1;
2884     private Bitmap mAvailThumbnailBitmap = null;
2885     private Canvas mThumbnailCanvas = null;
2886
2887     private Bitmap createThumbnailBitmap(ActivityClientRecord r) {
2888         Bitmap thumbnail = mAvailThumbnailBitmap;
2889         try {
2890             if (thumbnail == null) {
2891                 int w = mThumbnailWidth;
2892                 int h;
2893                 if (w < 0) {
2894                     Resources res = r.activity.getResources();
2895                     mThumbnailHeight = h =
2896                         res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
2897
2898                     mThumbnailWidth = w =
2899                         res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
2900                 } else {
2901                     h = mThumbnailHeight;
2902                 }
2903
2904                 // On platforms where we don't want thumbnails, set dims to (0,0)
2905                 if ((w > 0) && (h > 0)) {
2906                     thumbnail = Bitmap.createBitmap(r.activity.getResources().getDisplayMetrics(),
2907                             w, h, THUMBNAIL_FORMAT);
2908                     thumbnail.eraseColor(0);
2909                 }
2910             }
2911
2912             if (thumbnail != null) {
2913                 Canvas cv = mThumbnailCanvas;
2914                 if (cv == null) {
2915                     mThumbnailCanvas = cv = new Canvas();
2916                 }
2917     
2918                 cv.setBitmap(thumbnail);
2919                 if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
2920                     mAvailThumbnailBitmap = thumbnail;
2921                     thumbnail = null;
2922                 }
2923                 cv.setBitmap(null);
2924             }
2925
2926         } catch (Exception e) {
2927             if (!mInstrumentation.onException(r.activity, e)) {
2928                 throw new RuntimeException(
2929                         "Unable to create thumbnail of "
2930                         + r.intent.getComponent().toShortString()
2931                         + ": " + e.toString(), e);
2932             }
2933             thumbnail = null;
2934         }
2935
2936         return thumbnail;
2937     }
2938
2939     private void handlePauseActivity(IBinder token, boolean finished,
2940             boolean userLeaving, int configChanges) {
2941         ActivityClientRecord r = mActivities.get(token);
2942         if (r != null) {
2943             //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
2944             if (userLeaving) {
2945                 performUserLeavingActivity(r);
2946             }
2947
2948             r.activity.mConfigChangeFlags |= configChanges;
2949             performPauseActivity(token, finished, r.isPreHoneycomb());
2950
2951             // Make sure any pending writes are now committed.
2952             if (r.isPreHoneycomb()) {
2953                 QueuedWork.waitToFinish();
2954             }
2955
2956             // Tell the activity manager we have paused.
2957             try {
2958                 ActivityManagerNative.getDefault().activityPaused(token);
2959             } catch (RemoteException ex) {
2960             }
2961         }
2962     }
2963
2964     final void performUserLeavingActivity(ActivityClientRecord r) {
2965         mInstrumentation.callActivityOnUserLeaving(r.activity);
2966     }
2967
2968     final Bundle performPauseActivity(IBinder token, boolean finished,
2969             boolean saveState) {
2970         ActivityClientRecord r = mActivities.get(token);
2971         return r != null ? performPauseActivity(r, finished, saveState) : null;
2972     }
2973
2974     final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
2975             boolean saveState) {
2976         if (r.paused) {
2977             if (r.activity.mFinished) {
2978                 // If we are finishing, we won't call onResume() in certain cases.
2979                 // So here we likewise don't want to call onPause() if the activity
2980                 // isn't resumed.
2981                 return null;
2982             }
2983             RuntimeException e = new RuntimeException(
2984                     "Performing pause of activity that is not resumed: "
2985                     + r.intent.getComponent().toShortString());
2986             Slog.e(TAG, e.getMessage(), e);
2987         }
2988         Bundle state = null;
2989         if (finished) {
2990             r.activity.mFinished = true;
2991         }
2992         try {
2993             // Next have the activity save its current state and managed dialogs...
2994             if (!r.activity.mFinished && saveState) {
2995                 state = new Bundle();
2996                 state.setAllowFds(false);
2997                 mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
2998                 r.state = state;
2999             }
3000             // Now we are idle.
3001             r.activity.mCalled = false;
3002             mInstrumentation.callActivityOnPause(r.activity);
3003             EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
3004                     r.activity.getComponentName().getClassName());
3005             if (!r.activity.mCalled) {
3006                 throw new SuperNotCalledException(
3007                     "Activity " + r.intent.getComponent().toShortString() +
3008                     " did not call through to super.onPause()");
3009             }
3010
3011         } catch (SuperNotCalledException e) {
3012             throw e;
3013
3014         } catch (Exception e) {
3015             if (!mInstrumentation.onException(r.activity, e)) {
3016                 throw new RuntimeException(
3017                         "Unable to pause activity "
3018                         + r.intent.getComponent().toShortString()
3019                         + ": " + e.toString(), e);
3020             }
3021         }
3022         r.paused = true;
3023
3024         // Notify any outstanding on paused listeners
3025         ArrayList<OnActivityPausedListener> listeners;
3026         synchronized (mOnPauseListeners) {
3027             listeners = mOnPauseListeners.remove(r.activity);
3028         }
3029         int size = (listeners != null ? listeners.size() : 0);
3030         for (int i = 0; i < size; i++) {
3031             listeners.get(i).onPaused(r.activity);
3032         }
3033
3034         return state;
3035     }
3036
3037     final void performStopActivity(IBinder token, boolean saveState) {
3038         ActivityClientRecord r = mActivities.get(token);
3039         performStopActivityInner(r, null, false, saveState);
3040     }
3041
3042     private static class StopInfo implements Runnable {
3043         ActivityClientRecord activity;
3044         Bundle state;
3045         Bitmap thumbnail;
3046         CharSequence description;
3047
3048         @Override public void run() {
3049             // Tell activity manager we have been stopped.
3050             try {
3051                 if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity);
3052                 ActivityManagerNative.getDefault().activityStopped(
3053                     activity.token, state, thumbnail, description);
3054             } catch (RemoteException ex) {
3055             }
3056         }
3057     }
3058
3059     private static final class ProviderRefCount {
3060         public final IActivityManager.ContentProviderHolder holder;
3061         public final ProviderClientRecord client;
3062         public int stableCount;
3063         public int unstableCount;
3064
3065         // When this is set, the stable and unstable ref counts are 0 and
3066         // we have a pending operation scheduled to remove the ref count
3067         // from the activity manager.  On the activity manager we are still
3068         // holding an unstable ref, though it is not reflected in the counts
3069         // here.
3070         public boolean removePending;
3071
3072         ProviderRefCount(IActivityManager.ContentProviderHolder inHolder,
3073                 ProviderClientRecord inClient, int sCount, int uCount) {
3074             holder = inHolder;
3075             client = inClient;
3076             stableCount = sCount;
3077             unstableCount = uCount;
3078         }
3079     }
3080
3081     /**
3082      * Core implementation of stopping an activity.  Note this is a little
3083      * tricky because the server's meaning of stop is slightly different
3084      * than our client -- for the server, stop means to save state and give
3085      * it the result when it is done, but the window may still be visible.
3086      * For the client, we want to call onStop()/onStart() to indicate when
3087      * the activity's UI visibillity changes.
3088      */
3089     private void performStopActivityInner(ActivityClientRecord r,
3090             StopInfo info, boolean keepShown, boolean saveState) {
3091         if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
3092         Bundle state = null;
3093         if (r != null) {
3094             if (!keepShown && r.stopped) {
3095                 if (r.activity.mFinished) {
3096                     // If we are finishing, we won't call onResume() in certain
3097                     // cases.  So here we likewise don't want to call onStop()
3098                     // if the activity isn't resumed.
3099                     return;
3100                 }
3101                 RuntimeException e = new RuntimeException(
3102                         "Performing stop of activity that is not resumed: "
3103                         + r.intent.getComponent().toShortString());
3104                 Slog.e(TAG, e.getMessage(), e);
3105             }
3106
3107             if (info != null) {
3108                 try {
3109                     // First create a thumbnail for the activity...
3110                     // For now, don't create the thumbnail here; we are
3111                     // doing that by doing a screen snapshot.
3112                     info.thumbnail = null; //createThumbnailBitmap(r);
3113                     info.description = r.activity.onCreateDescription();
3114                 } catch (Exception e) {
3115                     if (!mInstrumentation.onException(r.activity, e)) {
3116                         throw new RuntimeException(
3117                                 "Unable to save state of activity "
3118                                 + r.intent.getComponent().toShortString()
3119                                 + ": " + e.toString(), e);
3120                     }
3121                 }
3122             }
3123
3124             // Next have the activity save its current state and managed dialogs...
3125             if (!r.activity.mFinished && saveState) {
3126                 if (r.state == null) {
3127                     state = new Bundle();
3128                     state.setAllowFds(false);
3129                     mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
3130                     r.state = state;
3131                 } else {
3132                     state = r.state;
3133                 }
3134             }
3135
3136             if (!keepShown) {
3137                 try {
3138                     // Now we are idle.
3139                     r.activity.performStop();
3140                 } catch (Exception e) {
3141                     if (!mInstrumentation.onException(r.activity, e)) {
3142                         throw new RuntimeException(
3143                                 "Unable to stop activity "
3144                                 + r.intent.getComponent().toShortString()
3145                                 + ": " + e.toString(), e);
3146                     }
3147                 }
3148                 r.stopped = true;
3149             }
3150
3151             r.paused = true;
3152         }
3153     }
3154
3155     private void updateVisibility(ActivityClientRecord r, boolean show) {
3156         View v = r.activity.mDecor;
3157         if (v != null) {
3158             if (show) {
3159                 if (!r.activity.mVisibleFromServer) {
3160                     r.activity.mVisibleFromServer = true;
3161                     mNumVisibleActivities++;
3162                     if (r.activity.mVisibleFromClient) {
3163                         r.activity.makeVisible();
3164                     }
3165                 }
3166                 if (r.newConfig != null) {
3167                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
3168                             + r.activityInfo.name + " with new config " + r.newConfig);
3169                     performConfigurationChanged(r.activity, r.newConfig);
3170                     freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
3171                     r.newConfig = null;
3172                 }
3173             } else {
3174                 if (r.activity.mVisibleFromServer) {
3175                     r.activity.mVisibleFromServer = false;
3176                     mNumVisibleActivities--;
3177                     v.setVisibility(View.INVISIBLE);
3178                 }
3179             }
3180         }
3181     }
3182
3183     private void handleStopActivity(IBinder token, boolean show, int configChanges) {
3184         ActivityClientRecord r = mActivities.get(token);
3185         r.activity.mConfigChangeFlags |= configChanges;
3186
3187         StopInfo info = new StopInfo();
3188         performStopActivityInner(r, info, show, true);
3189
3190         if (localLOGV) Slog.v(
3191             TAG, "Finishing stop of " + r + ": show=" + show
3192             + " win=" + r.window);
3193
3194         updateVisibility(r, show);
3195
3196         // Make sure any pending writes are now committed.
3197         if (!r.isPreHoneycomb()) {
3198             QueuedWork.waitToFinish();
3199         }
3200
3201         // Schedule the call to tell the activity manager we have
3202         // stopped.  We don't do this immediately, because we want to
3203         // have a chance for any other pending work (in particular memory
3204         // trim requests) to complete before you tell the activity
3205         // manager to proceed and allow us to go fully into the background.
3206         info.activity = r;
3207         info.state = r.state;
3208         mH.post(info);
3209     }
3210
3211     final void performRestartActivity(IBinder token) {
3212         ActivityClientRecord r = mActivities.get(token);
3213         if (r.stopped) {
3214             r.activity.performRestart();
3215             r.stopped = false;
3216         }
3217     }
3218
3219     private void handleWindowVisibility(IBinder token, boolean show) {
3220         ActivityClientRecord r = mActivities.get(token);
3221         
3222         if (r == null) {
3223             Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
3224             return;
3225         }
3226         
3227         if (!show && !r.stopped) {
3228             performStopActivityInner(r, null, show, false);
3229         } else if (show && r.stopped) {
3230             // If we are getting ready to gc after going to the background, well
3231             // we are back active so skip it.
3232             unscheduleGcIdler();
3233
3234             r.activity.performRestart();
3235             r.stopped = false;
3236         }
3237         if (r.activity.mDecor != null) {
3238             if (false) Slog.v(
3239                 TAG, "Handle window " + r + " visibility: " + show);
3240             updateVisibility(r, show);
3241         }
3242     }
3243
3244     private void handleSleeping(IBinder token, boolean sleeping) {
3245         ActivityClientRecord r = mActivities.get(token);
3246
3247         if (r == null) {
3248             Log.w(TAG, "handleSleeping: no activity for token " + token);
3249             return;
3250         }
3251
3252         if (sleeping) {
3253             if (!r.stopped && !r.isPreHoneycomb()) {
3254                 try {
3255                     // Now we are idle.
3256                     r.activity.performStop();
3257                 } catch (Exception e) {
3258                     if (!mInstrumentation.onException(r.activity, e)) {
3259                         throw new RuntimeException(
3260                                 "Unable to stop activity "
3261                                 + r.intent.getComponent().toShortString()
3262                                 + ": " + e.toString(), e);
3263                     }
3264                 }
3265                 r.stopped = true;
3266             }
3267
3268             // Make sure any pending writes are now committed.
3269             if (!r.isPreHoneycomb()) {
3270                 QueuedWork.waitToFinish();
3271             }
3272
3273             // Tell activity manager we slept.
3274             try {
3275                 ActivityManagerNative.getDefault().activitySlept(r.token);
3276             } catch (RemoteException ex) {
3277             }
3278         } else {
3279             if (r.stopped && r.activity.mVisibleFromServer) {
3280                 r.activity.performRestart();
3281                 r.stopped = false;
3282             }
3283         }
3284     }
3285
3286     private void handleSetCoreSettings(Bundle coreSettings) {
3287         synchronized (mPackages) {
3288             mCoreSettings = coreSettings;
3289         }
3290     }
3291
3292     private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
3293         LoadedApk apk = peekPackageInfo(data.pkg, false);
3294         if (apk != null) {
3295             apk.mCompatibilityInfo.set(data.info);
3296         }
3297         apk = peekPackageInfo(data.pkg, true);
3298         if (apk != null) {
3299             apk.mCompatibilityInfo.set(data.info);
3300         }
3301         handleConfigurationChanged(mConfiguration, data.info);
3302         WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
3303     }
3304
3305     private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
3306         final int N = results.size();
3307         for (int i=0; i<N; i++) {
3308             ResultInfo ri = results.get(i);
3309             try {
3310                 if (ri.mData != null) {
3311                     ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3312                 }
3313                 if (DEBUG_RESULTS) Slog.v(TAG,
3314                         "Delivering result to activity " + r + " : " + ri);
3315                 r.activity.dispatchActivityResult(ri.mResultWho,
3316                         ri.mRequestCode, ri.mResultCode, ri.mData);
3317             } catch (Exception e) {
3318                 if (!mInstrumentation.onException(r.activity, e)) {
3319                     throw new RuntimeException(
3320                             "Failure delivering result " + ri + " to activity "
3321                             + r.intent.getComponent().toShortString()
3322                             + ": " + e.toString(), e);
3323                 }
3324             }
3325         }
3326     }
3327
3328     private void handleSendResult(ResultData res) {
3329         ActivityClientRecord r = mActivities.get(res.token);
3330         if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
3331         if (r != null) {
3332             final boolean resumed = !r.paused;
3333             if (!r.activity.mFinished && r.activity.mDecor != null
3334                     && r.hideForNow && resumed) {
3335                 // We had hidden the activity because it started another
3336                 // one...  we have gotten a result back and we are not
3337                 // paused, so make sure our window is visible.
3338                 updateVisibility(r, true);
3339             }
3340             if (resumed) {
3341                 try {
3342                     // Now we are idle.
3343                     r.activity.mCalled = false;
3344                     r.activity.mTemporaryPause = true;
3345                     mInstrumentation.callActivityOnPause(r.activity);
3346                     if (!r.activity.mCalled) {
3347                         throw new SuperNotCalledException(
3348                             "Activity " + r.intent.getComponent().toShortString()
3349                             + " did not call through to super.onPause()");
3350                     }
3351                 } catch (SuperNotCalledException e) {
3352                     throw e;
3353                 } catch (Exception e) {
3354                     if (!mInstrumentation.onException(r.activity, e)) {
3355                         throw new RuntimeException(
3356                                 "Unable to pause activity "
3357                                 + r.intent.getComponent().toShortString()
3358                                 + ": " + e.toString(), e);
3359                     }
3360                 }
3361             }
3362             deliverResults(r, res.results);
3363             if (resumed) {
3364                 r.activity.performResume();
3365                 r.activity.mTemporaryPause = false;
3366             }
3367         }
3368     }
3369
3370     public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
3371         return performDestroyActivity(token, finishing, 0, false);
3372     }
3373
3374     private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
3375             int configChanges, boolean getNonConfigInstance) {
3376         ActivityClientRecord r = mActivities.get(token);
3377         Class activityClass = null;
3378         if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
3379         if (r != null) {
3380             activityClass = r.activity.getClass();
3381             r.activity.mConfigChangeFlags |= configChanges;
3382             if (finishing) {
3383                 r.activity.mFinished = true;
3384             }
3385             if (!r.paused) {
3386                 try {
3387                     r.activity.mCalled = false;
3388                     mInstrumentation.callActivityOnPause(r.activity);
3389                     EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
3390                             r.activity.getComponentName().getClassName());
3391                     if (!r.activity.mCalled) {
3392                         throw new SuperNotCalledException(
3393                             "Activity " + safeToComponentShortString(r.intent)
3394                             + " did not call through to super.onPause()");
3395                     }
3396                 } catch (SuperNotCalledException e) {
3397                     throw e;
3398                 } catch (Exception e) {
3399                     if (!mInstrumentation.onException(r.activity, e)) {
3400                         throw new RuntimeException(
3401                                 "Unable to pause activity "
3402                                 + safeToComponentShortString(r.intent)
3403                                 + ": " + e.toString(), e);
3404                     }
3405                 }
3406                 r.paused = true;
3407             }
3408             if (!r.stopped) {
3409                 try {
3410                     r.activity.performStop();
3411                 } catch (SuperNotCalledException e) {
3412                     throw e;
3413                 } catch (Exception e) {
3414                     if (!mInstrumentation.onException(r.activity, e)) {
3415                         throw new RuntimeException(
3416                                 "Unable to stop activity "
3417                                 + safeToComponentShortString(r.intent)
3418                                 + ": " + e.toString(), e);
3419                     }
3420                 }
3421                 r.stopped = true;
3422             }
3423             if (getNonConfigInstance) {
3424                 try {
3425                     r.lastNonConfigurationInstances
3426                             = r.activity.retainNonConfigurationInstances();
3427                 } catch (Exception e) {
3428                     if (!mInstrumentation.onException(r.activity, e)) {
3429                         throw new RuntimeException(
3430                                 "Unable to retain activity "
3431                                 + r.intent.getComponent().toShortString()
3432                                 + ": " + e.toString(), e);
3433                     }
3434                 }
3435             }
3436             try {
3437                 r.activity.mCalled = false;
3438                 mInstrumentation.callActivityOnDestroy(r.activity);
3439                 if (!r.activity.mCalled) {
3440                     throw new SuperNotCalledException(
3441                         "Activity " + safeToComponentShortString(r.intent) +
3442                         " did not call through to super.onDestroy()");
3443                 }
3444                 if (r.window != null) {
3445                     r.window.closeAllPanels();
3446                 }
3447             } catch (SuperNotCalledException e) {
3448                 throw e;
3449             } catch (Exception e) {
3450                 if (!mInstrumentation.onException(r.activity, e)) {
3451                     throw new RuntimeException(
3452                             "Unable to destroy activity " + safeToComponentShortString(r.intent)
3453                             + ": " + e.toString(), e);
3454                 }
3455             }
3456         }
3457         mActivities.remove(token);
3458         StrictMode.decrementExpectedActivityCount(activityClass);
3459         return r;
3460     }
3461
3462     private static String safeToComponentShortString(Intent intent) {
3463         ComponentName component = intent.getComponent();
3464         return component == null ? "[Unknown]" : component.toShortString();
3465     }
3466
3467     private void handleDestroyActivity(IBinder token, boolean finishing,
3468             int configChanges, boolean getNonConfigInstance) {
3469         ActivityClientRecord r = performDestroyActivity(token, finishing,
3470                 configChanges, getNonConfigInstance);
3471         if (r != null) {
3472             cleanUpPendingRemoveWindows(r);
3473             WindowManager wm = r.activity.getWindowManager();
3474             View v = r.activity.mDecor;
3475             if (v != null) {
3476                 if (r.activity.mVisibleFromServer) {
3477                     mNumVisibleActivities--;
3478                 }
3479                 IBinder wtoken = v.getWindowToken();
3480                 if (r.activity.mWindowAdded) {
3481                     if (r.onlyLocalRequest) {
3482                         // Hold off on removing this until the new activity's
3483                         // window is being added.
3484                         r.mPendingRemoveWindow = v;
3485                         r.mPendingRemoveWindowManager = wm;
3486                     } else {
3487                         wm.removeViewImmediate(v);
3488                     }
3489                 }
3490                 if (wtoken != null && r.mPendingRemoveWindow == null) {
3491                     WindowManagerGlobal.getInstance().closeAll(wtoken,
3492                             r.activity.getClass().getName(), "Activity");
3493                 }
3494                 r.activity.mDecor = null;
3495             }
3496             if (r.mPendingRemoveWindow == null) {
3497                 // If we are delaying the removal of the activity window, then
3498                 // we can't clean up all windows here.  Note that we can't do
3499                 // so later either, which means any windows that aren't closed
3500                 // by the app will leak.  Well we try to warning them a lot
3501                 // about leaking windows, because that is a bug, so if they are
3502                 // using this recreate facility then they get to live with leaks.
3503                 WindowManagerGlobal.getInstance().closeAll(token,
3504                         r.activity.getClass().getName(), "Activity");
3505             }
3506
3507             // Mocked out contexts won't be participating in the normal
3508             // process lifecycle, but if we're running with a proper
3509             // ApplicationContext we need to have it tear down things
3510             // cleanly.
3511             Context c = r.activity.getBaseContext();
3512             if (c instanceof ContextImpl) {
3513                 ((ContextImpl) c).scheduleFinalCleanup(
3514                         r.activity.getClass().getName(), "Activity");
3515             }
3516         }
3517         if (finishing) {
3518             try {
3519                 ActivityManagerNative.getDefault().activityDestroyed(token);
3520             } catch (RemoteException ex) {
3521                 // If the system process has died, it's game over for everyone.
3522             }
3523         }
3524     }
3525
3526     public final void requestRelaunchActivity(IBinder token,
3527             List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
3528             int configChanges, boolean notResumed, Configuration config,
3529             boolean fromServer) {
3530         ActivityClientRecord target = null;
3531
3532         synchronized (mPackages) {
3533             for (int i=0; i<mRelaunchingActivities.size(); i++) {
3534                 ActivityClientRecord r = mRelaunchingActivities.get(i);
3535                 if (r.token == token) {
3536                     target = r;
3537                     if (pendingResults != null) {
3538                         if (r.pendingResults != null) {
3539                             r.pendingResults.addAll(pendingResults);
3540                         } else {
3541                             r.pendingResults = pendingResults;
3542                         }
3543                     }
3544                     if (pendingNewIntents != null) {
3545                         if (r.pendingIntents != null) {
3546                             r.pendingIntents.addAll(pendingNewIntents);
3547                         } else {
3548                             r.pendingIntents = pendingNewIntents;
3549                         }
3550                     }
3551                     break;
3552                 }
3553             }
3554
3555             if (target == null) {
3556                 target = new ActivityClientRecord();
3557                 target.token = token;
3558                 target.pendingResults = pendingResults;
3559                 target.pendingIntents = pendingNewIntents;
3560                 if (!fromServer) {
3561                     ActivityClientRecord existing = mActivities.get(token);
3562                     if (existing != null) {
3563                         target.startsNotResumed = existing.paused;
3564                     }
3565                     target.onlyLocalRequest = true;
3566                 }
3567                 mRelaunchingActivities.add(target);
3568                 queueOrSendMessage(H.RELAUNCH_ACTIVITY, target);
3569             }
3570
3571             if (fromServer) {
3572                 target.startsNotResumed = notResumed;
3573                 target.onlyLocalRequest = false;
3574             }
3575             if (config != null) {
3576                 target.createdConfig = config;
3577             }
3578             target.pendingConfigChanges |= configChanges;
3579         }
3580     }
3581
3582     private void handleRelaunchActivity(ActivityClientRecord tmp) {
3583         // If we are getting ready to gc after going to the background, well
3584         // we are back active so skip it.
3585         unscheduleGcIdler();
3586
3587         Configuration changedConfig = null;
3588         int configChanges = 0;
3589
3590         // First: make sure we have the most recent configuration and most
3591         // recent version of the activity, or skip it if some previous call
3592         // had taken a more recent version.
3593         synchronized (mPackages) {
3594             int N = mRelaunchingActivities.size();
3595             IBinder token = tmp.token;
3596             tmp = null;
3597             for (int i=0; i<N; i++) {
3598                 ActivityClientRecord r = mRelaunchingActivities.get(i);
3599                 if (r.token == token) {
3600                     tmp = r;
3601                     configChanges |= tmp.pendingConfigChanges;
3602                     mRelaunchingActivities.remove(i);
3603                     i--;
3604                     N--;
3605                 }
3606             }
3607
3608             if (tmp == null) {
3609                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
3610                 return;
3611             }
3612
3613             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3614                     + tmp.token + " with configChanges=0x"
3615                     + Integer.toHexString(configChanges));
3616
3617             if (mPendingConfiguration != null) {
3618                 changedConfig = mPendingConfiguration;
3619                 mPendingConfiguration = null;
3620             }
3621         }
3622
3623         if (tmp.createdConfig != null) {
3624             // If the activity manager is passing us its current config,
3625             // assume that is really what we want regardless of what we
3626             // may have pending.
3627             if (mConfiguration == null
3628                     || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
3629                             && mConfiguration.diff(tmp.createdConfig) != 0)) {
3630                 if (changedConfig == null
3631                         || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
3632                     changedConfig = tmp.createdConfig;
3633                 }
3634             }
3635         }
3636         
3637         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3638                 + tmp.token + ": changedConfig=" + changedConfig);
3639         
3640         // If there was a pending configuration change, execute it first.
3641         if (changedConfig != null) {
3642             mCurDefaultDisplayDpi = changedConfig.densityDpi;
3643             updateDefaultDensity();
3644             handleConfigurationChanged(changedConfig, null);
3645         }
3646
3647         ActivityClientRecord r = mActivities.get(tmp.token);
3648         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
3649         if (r == null) {
3650             return;
3651         }
3652
3653         r.activity.mConfigChangeFlags |= configChanges;
3654         r.onlyLocalRequest = tmp.onlyLocalRequest;
3655         Intent currentIntent = r.activity.mIntent;
3656
3657         r.activity.mChangingConfigurations = true;
3658
3659         // Need to ensure state is saved.
3660         if (!r.paused) {
3661             performPauseActivity(r.token, false, r.isPreHoneycomb());
3662         }
3663         if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
3664             r.state = new Bundle();
3665             r.state.setAllowFds(false);
3666             mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
3667         }
3668
3669         handleDestroyActivity(r.token, false, configChanges, true);
3670
3671         r.activity = null;
3672         r.window = null;
3673         r.hideForNow = false;
3674         r.nextIdle = null;
3675         // Merge any pending results and pending intents; don't just replace them
3676         if (tmp.pendingResults != null) {
3677             if (r.pendingResults == null) {
3678                 r.pendingResults = tmp.pendingResults;
3679             } else {
3680                 r.pendingResults.addAll(tmp.pendingResults);
3681             }
3682         }
3683         if (tmp.pendingIntents != null) {
3684             if (r.pendingIntents == null) {
3685                 r.pendingIntents = tmp.pendingIntents;
3686             } else {
3687                 r.pendingIntents.addAll(tmp.pendingIntents);
3688             }
3689         }
3690         r.startsNotResumed = tmp.startsNotResumed;
3691
3692         handleLaunchActivity(r, currentIntent);
3693     }
3694
3695     private void handleRequestThumbnail(IBinder token) {
3696         ActivityClientRecord r = mActivities.get(token);
3697         Bitmap thumbnail = createThumbnailBitmap(r);
3698         CharSequence description = null;
3699         try {
3700             description = r.activity.onCreateDescription();
3701         } catch (Exception e) {
3702             if (!mInstrumentation.onException(r.activity, e)) {
3703                 throw new RuntimeException(
3704                         "Unable to create description of activity "
3705                         + r.intent.getComponent().toShortString()
3706                         + ": " + e.toString(), e);
3707             }
3708         }
3709         //System.out.println("Reporting top thumbnail " + thumbnail);
3710         try {
3711             ActivityManagerNative.getDefault().reportThumbnail(
3712                 token, thumbnail, description);
3713         } catch (RemoteException ex) {
3714         }
3715     }
3716
3717     ArrayList<ComponentCallbacks2> collectComponentCallbacks(
3718             boolean allActivities, Configuration newConfig) {
3719         ArrayList<ComponentCallbacks2> callbacks
3720                 = new ArrayList<ComponentCallbacks2>();
3721
3722         synchronized (mPackages) {
3723             final int N = mAllApplications.size();
3724             for (int i=0; i<N; i++) {
3725                 callbacks.add(mAllApplications.get(i));
3726             }
3727             if (mActivities.size() > 0) {
3728                 for (ActivityClientRecord ar : mActivities.values()) {
3729                     Activity a = ar.activity;
3730                     if (a != null) {
3731                         Configuration thisConfig = applyConfigCompatMainThread(mCurDefaultDisplayDpi,
3732                                 newConfig, ar.packageInfo.mCompatibilityInfo.getIfNeeded());
3733                         if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
3734                             // If the activity is currently resumed, its configuration
3735                             // needs to change right now.
3736                             callbacks.add(a);
3737                         } else if (thisConfig != null) {
3738                             // Otherwise, we will tell it about the change
3739                             // the next time it is resumed or shown.  Note that
3740                             // the activity manager may, before then, decide the
3741                             // activity needs to be destroyed to handle its new
3742                             // configuration.
3743                             if (DEBUG_CONFIGURATION) {
3744                                 Slog.v(TAG, "Setting activity "
3745                                         + ar.activityInfo.name + " newConfig=" + thisConfig);
3746                             }
3747                             ar.newConfig = thisConfig;
3748                         }
3749                     }
3750                 }
3751             }
3752             if (mServices.size() > 0) {
3753                 for (Service service : mServices.values()) {
3754                     callbacks.add(service);
3755                 }
3756             }
3757         }
3758         synchronized (mProviderMap) {
3759             if (mLocalProviders.size() > 0) {
3760                 for (ProviderClientRecord providerClientRecord : mLocalProviders.values()) {
3761                     callbacks.add(providerClientRecord.mLocalProvider);
3762                 }
3763             }
3764         }
3765
3766         return callbacks;
3767     }
3768
3769     private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) {
3770         // Only for Activity objects, check that they actually call up to their
3771         // superclass implementation.  ComponentCallbacks2 is an interface, so
3772         // we check the runtime type and act accordingly.
3773         Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
3774         if (activity != null) {
3775             activity.mCalled = false;
3776         }
3777
3778         boolean shouldChangeConfig = false;
3779         if ((activity == null) || (activity.mCurrentConfig == null)) {
3780             shouldChangeConfig = true;
3781         } else {
3782
3783             // If the new config is the same as the config this Activity
3784             // is already running with then don't bother calling
3785             // onConfigurationChanged
3786             int diff = activity.mCurrentConfig.diff(config);
3787             if (diff != 0) {
3788                 // If this activity doesn't handle any of the config changes
3789                 // then don't bother calling onConfigurationChanged as we're
3790                 // going to destroy it.
3791                 if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {
3792                     shouldChangeConfig = true;
3793                 }
3794             }
3795         }
3796
3797         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
3798                 + ": shouldChangeConfig=" + shouldChangeConfig);
3799         if (shouldChangeConfig) {
3800             cb.onConfigurationChanged(config);
3801
3802             if (activity != null) {
3803                 if (!activity.mCalled) {
3804                     throw new SuperNotCalledException(
3805                             "Activity " + activity.getLocalClassName() +
3806                         " did not call through to super.onConfigurationChanged()");
3807                 }
3808                 activity.mConfigChangeFlags = 0;
3809                 activity.mCurrentConfig = new Configuration(config);
3810             }
3811         }
3812     }
3813
3814     public final void applyConfigurationToResources(Configuration config) {
3815         synchronized (mPackages) {
3816             applyConfigurationToResourcesLocked(config, null);
3817         }
3818     }
3819
3820     final boolean applyConfigurationToResourcesLocked(Configuration config,
3821             CompatibilityInfo compat) {
3822         if (mResConfiguration == null) {
3823             mResConfiguration = new Configuration();
3824         }
3825         if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
3826             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
3827                     + mResConfiguration.seq + ", newSeq=" + config.seq);
3828             return false;
3829         }
3830         int changes = mResConfiguration.updateFrom(config);
3831         flushDisplayMetricsLocked();
3832         DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(
3833                 Display.DEFAULT_DISPLAY, null);
3834
3835         if (compat != null && (mResCompatibilityInfo == null ||
3836                 !mResCompatibilityInfo.equals(compat))) {
3837             mResCompatibilityInfo = compat;
3838             changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
3839                     | ActivityInfo.CONFIG_SCREEN_SIZE
3840                     | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
3841         }
3842
3843         // set it for java, this also affects newly created Resources
3844         if (config.locale != null) {
3845             Locale.setDefault(config.locale);
3846         }
3847
3848         Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
3849
3850         ApplicationPackageManager.configurationChanged();
3851         //Slog.i(TAG, "Configuration changed in " + currentPackageName());
3852
3853         Configuration tmpConfig = null;
3854
3855         Iterator<Map.Entry<ResourcesKey, WeakReference<Resources>>> it =
3856                 mActiveResources.entrySet().iterator();
3857         while (it.hasNext()) {
3858             Map.Entry<ResourcesKey, WeakReference<Resources>> entry = it.next();
3859             Resources r = entry.getValue().get();
3860             if (r != null) {
3861                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
3862                         + r + " config to: " + config);
3863                 int displayId = entry.getKey().mDisplayId;
3864                 boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
3865                 DisplayMetrics dm = defaultDisplayMetrics;
3866                 Configuration overrideConfig = entry.getKey().mOverrideConfiguration;
3867                 if (!isDefaultDisplay || overrideConfig != null) {
3868                     if (tmpConfig == null) {
3869                         tmpConfig = new Configuration();
3870                     }
3871                     tmpConfig.setTo(config);
3872                     if (!isDefaultDisplay) {
3873                         dm = getDisplayMetricsLocked(displayId, null);
3874                         applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
3875                     }
3876                     if (overrideConfig != null) {
3877                         tmpConfig.updateFrom(overrideConfig);
3878                     }
3879                     r.updateConfiguration(tmpConfig, dm, compat);
3880                 } else {
3881                     r.updateConfiguration(config, dm, compat);
3882                 }
3883                 //Slog.i(TAG, "Updated app resources " + v.getKey()
3884                 //        + " " + r + ": " + r.getConfiguration());
3885             } else {
3886                 //Slog.i(TAG, "Removing old resources " + v.getKey());
3887                 it.remove();
3888             }
3889         }
3890         
3891         return changes != 0;
3892     }
3893
3894     final void applyNonDefaultDisplayMetricsToConfigurationLocked(
3895             DisplayMetrics dm, Configuration config) {
3896         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
3897         config.densityDpi = dm.densityDpi;
3898         config.screenWidthDp = (int)(dm.widthPixels / dm.density);
3899         config.screenHeightDp = (int)(dm.heightPixels / dm.density);
3900         int sl = Configuration.resetScreenLayout(config.screenLayout);
3901         if (dm.widthPixels > dm.heightPixels) {
3902             config.orientation = Configuration.ORIENTATION_LANDSCAPE;
3903             config.screenLayout = Configuration.reduceScreenLayout(sl,
3904                     config.screenWidthDp, config.screenHeightDp);
3905         } else {
3906             config.orientation = Configuration.ORIENTATION_PORTRAIT;
3907             config.screenLayout = Configuration.reduceScreenLayout(sl,
3908                     config.screenHeightDp, config.screenWidthDp);
3909         }
3910         config.smallestScreenWidthDp = config.screenWidthDp; // assume screen does not rotate
3911         config.compatScreenWidthDp = config.screenWidthDp;
3912         config.compatScreenHeightDp = config.screenHeightDp;
3913         config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
3914     }
3915
3916     final Configuration applyCompatConfiguration(int displayDensity) {
3917         Configuration config = mConfiguration;
3918         if (mCompatConfiguration == null) {
3919             mCompatConfiguration = new Configuration();
3920         }
3921         mCompatConfiguration.setTo(mConfiguration);
3922         if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
3923             mResCompatibilityInfo.applyToConfiguration(displayDensity, mCompatConfiguration);
3924             config = mCompatConfiguration;
3925         }
3926         return config;
3927     }
3928
3929     final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
3930
3931         int configDiff = 0;
3932
3933         synchronized (mPackages) {
3934             if (mPendingConfiguration != null) {
3935                 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
3936                     config = mPendingConfiguration;
3937                     mCurDefaultDisplayDpi = config.densityDpi;
3938                     updateDefaultDensity();
3939                 }
3940                 mPendingConfiguration = null;
3941             }
3942
3943             if (config == null) {
3944                 return;
3945             }
3946             
3947             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
3948                     + config);
3949         
3950             applyConfigurationToResourcesLocked(config, compat);
3951             
3952             if (mConfiguration == null) {
3953                 mConfiguration = new Configuration();
3954             }
3955             if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
3956                 return;
3957             }
3958             configDiff = mConfiguration.diff(config);
3959             mConfiguration.updateFrom(config);
3960             config = applyCompatConfiguration(mCurDefaultDisplayDpi);
3961         }
3962
3963         ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
3964
3965         // Cleanup hardware accelerated stuff
3966         WindowManagerGlobal.getInstance().trimLocalMemory();
3967
3968         freeTextLayoutCachesIfNeeded(configDiff);
3969
3970         if (callbacks != null) {
3971             final int N = callbacks.size();
3972             for (int i=0; i<N; i++) {
3973                 performConfigurationChanged(callbacks.get(i), config);
3974             }
3975         }
3976     }
3977
3978     final void freeTextLayoutCachesIfNeeded(int configDiff) {
3979         if (configDiff != 0) {
3980             // Ask text layout engine to free its caches if there is a locale change
3981             boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
3982             if (hasLocaleConfigChange) {
3983                 Canvas.freeTextLayoutCaches();
3984                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
3985             }
3986         }
3987     }
3988
3989     final void handleActivityConfigurationChanged(IBinder token) {
3990         ActivityClientRecord r = mActivities.get(token);
3991         if (r == null || r.activity == null) {
3992             return;
3993         }
3994
3995         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
3996                 + r.activityInfo.name);
3997         
3998         performConfigurationChanged(r.activity, mCompatConfiguration);
3999
4000         freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration));
4001     }
4002
4003     final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) {
4004         if (start) {
4005             try {
4006                 switch (profileType) {
4007                     default:                        
4008                         mProfiler.setProfiler(pcd.path, pcd.fd);
4009                         mProfiler.autoStopProfiler = false;
4010                         mProfiler.startProfiling();
4011                         break;
4012                 }
4013             } catch (RuntimeException e) {
4014                 Slog.w(TAG, "Profiling failed on path " + pcd.path
4015                         + " -- can the process access this path?");
4016             } finally {
4017                 try {
4018                     pcd.fd.close();
4019                 } catch (IOException e) {
4020                     Slog.w(TAG, "Failure closing profile fd", e);
4021                 }
4022             }
4023         } else {
4024             switch (profileType) {
4025                 default:
4026                     mProfiler.stopProfiling();
4027                     break;
4028             }
4029         }
4030     }
4031
4032     static final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
4033         if (managed) {
4034             try {
4035                 Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
4036             } catch (IOException e) {
4037                 Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
4038                         + " -- can the process access this path?");
4039             } finally {
4040                 try {
4041                     dhd.fd.close();
4042                 } catch (IOException e) {
4043                     Slog.w(TAG, "Failure closing profile fd", e);
4044                 }
4045             }
4046         } else {
4047             Debug.dumpNativeHeap(dhd.fd.getFileDescriptor());
4048         }
4049     }
4050
4051     final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
4052         boolean hasPkgInfo = false;
4053         if (packages != null) {
4054             for (int i=packages.length-1; i>=0; i--) {
4055                 //Slog.i(TAG, "Cleaning old package: " + packages[i]);
4056                 if (!hasPkgInfo) {
4057                     WeakReference<LoadedApk> ref;
4058                     ref = mPackages.get(packages[i]);
4059                     if (ref != null && ref.get() != null) {
4060                         hasPkgInfo = true;
4061                     } else {
4062                         ref = mResourcePackages.get(packages[i]);
4063                         if (ref != null && ref.get() != null) {
4064                             hasPkgInfo = true;
4065                         }
4066                     }
4067                 }
4068                 mPackages.remove(packages[i]);
4069                 mResourcePackages.remove(packages[i]);
4070             }
4071         }
4072         ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
4073                 hasPkgInfo);
4074     }
4075         
4076     final void handleLowMemory() {
4077         ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
4078
4079         final int N = callbacks.size();
4080         for (int i=0; i<N; i++) {
4081             callbacks.get(i).onLowMemory();
4082         }
4083
4084         // Ask SQLite to free up as much memory as it can, mostly from its page caches.
4085         if (Process.myUid() != Process.SYSTEM_UID) {
4086             int sqliteReleased = SQLiteDatabase.releaseMemory();
4087             EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
4088         }
4089
4090         // Ask graphics to free up as much as possible (font/image caches)
4091         Canvas.freeCaches();
4092
4093         // Ask text layout engine to free also as much as possible
4094         Canvas.freeTextLayoutCaches();
4095
4096         BinderInternal.forceGc("mem");
4097     }
4098
4099     final void handleTrimMemory(int level) {
4100         if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
4101
4102         final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance();
4103         windowManager.startTrimMemory(level);
4104
4105         ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
4106
4107         final int N = callbacks.size();
4108         for (int i = 0; i < N; i++) {
4109             callbacks.get(i).onTrimMemory(level);
4110         }
4111
4112         windowManager.endTrimMemory();
4113     }
4114
4115     private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
4116         if (Process.isIsolated()) {
4117             // Isolated processes aren't going to do UI.
4118             return;
4119         }
4120         try {
4121             int uid = Process.myUid();
4122             String[] packages = getPackageManager().getPackagesForUid(uid);
4123
4124             // If there are several packages in this application we won't
4125             // initialize the graphics disk caches 
4126             if (packages != null && packages.length == 1) {
4127                 HardwareRenderer.setupDiskCache(cacheDir);
4128                 RenderScript.setupDiskCache(cacheDir);
4129             }
4130         } catch (RemoteException e) {
4131             // Ignore
4132         }
4133     }
4134
4135     private void updateDefaultDensity() {
4136         if (mCurDefaultDisplayDpi != Configuration.DENSITY_DPI_UNDEFINED
4137                 && mCurDefaultDisplayDpi != DisplayMetrics.DENSITY_DEVICE
4138                 && !mDensityCompatMode) {
4139             Slog.i(TAG, "Switching default density from "
4140                     + DisplayMetrics.DENSITY_DEVICE + " to "
4141                     + mCurDefaultDisplayDpi);
4142             DisplayMetrics.DENSITY_DEVICE = mCurDefaultDisplayDpi;
4143             Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4144         }
4145     }
4146
4147     private void handleBindApplication(AppBindData data) {
4148         mBoundApplication = data;
4149         mConfiguration = new Configuration(data.config);
4150         mCompatConfiguration = new Configuration(data.config);
4151
4152         mProfiler = new Profiler();
4153         mProfiler.profileFile = data.initProfileFile;
4154         mProfiler.profileFd = data.initProfileFd;
4155         mProfiler.autoStopProfiler = data.initAutoStopProfiler;
4156
4157         // send up app name; do this *before* waiting for debugger
4158         Process.setArgV0(data.processName);
4159         android.ddm.DdmHandleAppName.setAppName(data.processName,
4160                                                 UserHandle.myUserId());
4161
4162         if (data.persistent) {
4163             // Persistent processes on low-memory devices do not get to
4164             // use hardware accelerated drawing, since this can add too much
4165             // overhead to the process.
4166             if (!ActivityManager.isHighEndGfx()) {
4167                 HardwareRenderer.disable(false);
4168             }
4169         }
4170         
4171         if (mProfiler.profileFd != null) {
4172             mProfiler.startProfiling();
4173         }
4174
4175         // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
4176         // implementation to use the pool executor.  Normally, we use the
4177         // serialized executor as the default. This has to happen in the
4178         // main thread so the main looper is set right.
4179         if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
4180             AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
4181         }
4182
4183         /*
4184          * Before spawning a new process, reset the time zone to be the system time zone.
4185          * This needs to be done because the system time zone could have changed after the
4186          * the spawning of this process. Without doing this this process would have the incorrect
4187          * system time zone.
4188          */
4189         TimeZone.setDefault(null);
4190
4191         /*
4192          * Initialize the default locale in this process for the reasons we set the time zone.
4193          */
4194         Locale.setDefault(data.config.locale);
4195
4196         /*
4197          * Update the system configuration since its preloaded and might not
4198          * reflect configuration changes. The configuration object passed
4199          * in AppBindData can be safely assumed to be up to date
4200          */
4201         applyConfigurationToResourcesLocked(data.config, data.compatInfo);
4202         mCurDefaultDisplayDpi = data.config.densityDpi;
4203         applyCompatConfiguration(mCurDefaultDisplayDpi);
4204
4205         data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
4206
4207         /**
4208          * Switch this process to density compatibility mode if needed.
4209          */
4210         if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
4211                 == 0) {
4212             mDensityCompatMode = true;
4213             Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4214         }
4215         updateDefaultDensity();
4216
4217         final ContextImpl appContext = new ContextImpl();
4218         appContext.init(data.info, null, this);
4219         if (!Process.isIsolated()) {
4220             final File cacheDir = appContext.getCacheDir();
4221
4222             if (cacheDir != null) {
4223                 // Provide a usable directory for temporary files
4224                 System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
4225     
4226                 setupGraphicsSupport(data.info, cacheDir);
4227             } else {
4228                 Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
4229             }
4230         }
4231         /**
4232          * For system applications on userdebug/eng builds, log stack
4233          * traces of disk and network access to dropbox for analysis.
4234          */
4235         if ((data.appInfo.flags &
4236              (ApplicationInfo.FLAG_SYSTEM |
4237               ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
4238             StrictMode.conditionallyEnableDebugLogging();
4239         }
4240
4241         /**
4242          * For apps targetting SDK Honeycomb or later, we don't allow
4243          * network usage on the main event loop / UI thread.
4244          *
4245          * Note to those grepping:  this is what ultimately throws
4246          * NetworkOnMainThreadException ...
4247          */
4248         if (data.appInfo.targetSdkVersion > 9) {
4249             StrictMode.enableDeathOnNetwork();
4250         }
4251
4252         if (data.debugMode != IApplicationThread.DEBUG_OFF) {
4253             // XXX should have option to change the port.
4254             Debug.changeDebugPort(8100);
4255             if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
4256                 Slog.w(TAG, "Application " + data.info.getPackageName()
4257                       + " is waiting for the debugger on port 8100...");
4258
4259                 IActivityManager mgr = ActivityManagerNative.getDefault();
4260                 try {
4261                     mgr.showWaitingForDebugger(mAppThread, true);
4262                 } catch (RemoteException ex) {
4263                 }
4264
4265                 Debug.waitForDebugger();
4266
4267                 try {
4268                     mgr.showWaitingForDebugger(mAppThread, false);
4269                 } catch (RemoteException ex) {
4270                 }
4271
4272             } else {
4273                 Slog.w(TAG, "Application " + data.info.getPackageName()
4274                       + " can be debugged on port 8100...");
4275             }
4276         }
4277
4278         // Enable OpenGL tracing if required
4279         if (data.enableOpenGlTrace) {
4280             GLUtils.enableTracing();
4281         }
4282
4283         /**
4284          * Initialize the default http proxy in this process for the reasons we set the time zone.
4285          */
4286         IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
4287         if (b != null) {
4288             // In pre-boot mode (doing initial launch to collect password), not
4289             // all system is up.  This includes the connectivity service, so don't
4290             // crash if we can't get it.
4291             IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
4292             try {
4293                 ProxyProperties proxyProperties = service.getProxy();
4294                 Proxy.setHttpProxySystemProperty(proxyProperties);
4295             } catch (RemoteException e) {}
4296         }
4297
4298         if (data.instrumentationName != null) {
4299             InstrumentationInfo ii = null;
4300             try {
4301                 ii = appContext.getPackageManager().
4302                     getInstrumentationInfo(data.instrumentationName, 0);
4303             } catch (PackageManager.NameNotFoundException e) {
4304             }
4305             if (ii == null) {
4306                 throw new RuntimeException(
4307                     "Unable to find instrumentation info for: "
4308                     + data.instrumentationName);
4309             }
4310
4311             mInstrumentationAppDir = ii.sourceDir;
4312             mInstrumentationAppLibraryDir = ii.nativeLibraryDir;
4313             mInstrumentationAppPackage = ii.packageName;
4314             mInstrumentedAppDir = data.info.getAppDir();
4315             mInstrumentedAppLibraryDir = data.info.getLibDir();
4316
4317             ApplicationInfo instrApp = new ApplicationInfo();
4318             instrApp.packageName = ii.packageName;
4319             instrApp.sourceDir = ii.sourceDir;
4320             instrApp.publicSourceDir = ii.publicSourceDir;
4321             instrApp.dataDir = ii.dataDir;
4322             instrApp.nativeLibraryDir = ii.nativeLibraryDir;
4323             LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
4324                     appContext.getClassLoader(), false, true);
4325             ContextImpl instrContext = new ContextImpl();
4326             instrContext.init(pi, null, this);
4327
4328             try {
4329                 java.lang.ClassLoader cl = instrContext.getClassLoader();
4330                 mInstrumentation = (Instrumentation)
4331                     cl.loadClass(data.instrumentationName.getClassName()).newInstance();
4332             } catch (Exception e) {
4333                 throw new RuntimeException(
4334                     "Unable to instantiate instrumentation "
4335                     + data.instrumentationName + ": " + e.toString(), e);
4336             }
4337
4338             mInstrumentation.init(this, instrContext, appContext,
4339                     new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
4340
4341             if (mProfiler.profileFile != null && !ii.handleProfiling
4342                     && mProfiler.profileFd == null) {
4343                 mProfiler.handlingProfiling = true;
4344                 File file = new File(mProfiler.profileFile);
4345                 file.getParentFile().mkdirs();
4346                 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
4347             }
4348
4349         } else {
4350             mInstrumentation = new Instrumentation();
4351         }
4352
4353         if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
4354             dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
4355         }
4356
4357         // Allow disk access during application and provider setup. This could
4358         // block processing ordered broadcasts, but later processing would
4359         // probably end up doing the same disk access.
4360         final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
4361         try {
4362             // If the app is being launched for full backup or restore, bring it up in
4363             // a restricted environment with the base application class.
4364             Application app = data.info.makeApplication(data.restrictedBackupMode, null);
4365             mInitialApplication = app;
4366
4367             // don't bring up providers in restricted mode; they may depend on the
4368             // app's custom Application class
4369             if (!data.restrictedBackupMode) {
4370                 List<ProviderInfo> providers = data.providers;
4371                 if (providers != null) {
4372                     installContentProviders(app, providers);
4373                     // For process that contains content providers, we want to
4374                     // ensure that the JIT is enabled "at some point".
4375                     mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
4376                 }
4377             }
4378
4379             // Do this after providers, since instrumentation tests generally start their
4380             // test thread at this point, and we don't want that racing.
4381             try {
4382                 mInstrumentation.onCreate(data.instrumentationArgs);
4383             }
4384             catch (Exception e) {
4385                 throw new RuntimeException(
4386                     "Exception thrown in onCreate() of "
4387                     + data.instrumentationName + ": " + e.toString(), e);
4388             }
4389
4390             try {
4391                 mInstrumentation.callApplicationOnCreate(app);
4392             } catch (Exception e) {
4393                 if (!mInstrumentation.onException(app, e)) {
4394                     throw new RuntimeException(
4395                         "Unable to create application " + app.getClass().getName()
4396                         + ": " + e.toString(), e);
4397                 }
4398             }
4399         } finally {
4400             StrictMode.setThreadPolicy(savedPolicy);
4401         }
4402     }
4403
4404     /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
4405         IActivityManager am = ActivityManagerNative.getDefault();
4406         if (mProfiler.profileFile != null && mProfiler.handlingProfiling
4407                 && mProfiler.profileFd == null) {
4408             Debug.stopMethodTracing();
4409         }
4410         //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
4411         //      + ", app thr: " + mAppThread);
4412         try {
4413             am.finishInstrumentation(mAppThread, resultCode, results);
4414         } catch (RemoteException ex) {
4415         }
4416     }
4417
4418     private void installContentProviders(
4419             Context context, List<ProviderInfo> providers) {
4420         final ArrayList<IActivityManager.ContentProviderHolder> results =
4421             new ArrayList<IActivityManager.ContentProviderHolder>();
4422
4423         for (ProviderInfo cpi : providers) {
4424             if (DEBUG_PROVIDER) {
4425                 StringBuilder buf = new StringBuilder(128);
4426                 buf.append("Pub ");
4427                 buf.append(cpi.authority);
4428                 buf.append(": ");
4429                 buf.append(cpi.name);
4430                 Log.i(TAG, buf.toString());
4431             }
4432             IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
4433                     false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
4434             if (cph != null) {
4435                 cph.noReleaseNeeded = true;
4436                 results.add(cph);
4437             }
4438         }
4439
4440         try {
4441             ActivityManagerNative.getDefault().publishContentProviders(
4442                 getApplicationThread(), results);
4443         } catch (RemoteException ex) {
4444         }
4445     }
4446
4447     public final IContentProvider acquireProvider(
4448             Context c, String auth, int userId, boolean stable) {
4449         final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
4450         if (provider != null) {
4451             return provider;
4452         }
4453
4454         // There is a possible race here.  Another thread may try to acquire
4455         // the same provider at the same time.  When this happens, we want to ensure
4456         // that the first one wins.
4457         // Note that we cannot hold the lock while acquiring and installing the
4458         // provider since it might take a long time to run and it could also potentially
4459         // be re-entrant in the case where the provider is in the same process.
4460         IActivityManager.ContentProviderHolder holder = null;
4461         try {
4462             holder = ActivityManagerNative.getDefault().getContentProvider(
4463                     getApplicationThread(), auth, userId, stable);
4464         } catch (RemoteException ex) {
4465         }
4466         if (holder == null) {
4467             Slog.e(TAG, "Failed to find provider info for " + auth);
4468             return null;
4469         }
4470
4471         // Install provider will increment the reference count for us, and break
4472         // any ties in the race.
4473         holder = installProvider(c, holder, holder.info,
4474                 true /*noisy*/, holder.noReleaseNeeded, stable);
4475         return holder.provider;
4476     }
4477
4478     private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
4479         if (stable) {
4480             prc.stableCount += 1;
4481             if (prc.stableCount == 1) {
4482                 // We are acquiring a new stable reference on the provider.
4483                 int unstableDelta;
4484                 if (prc.removePending) {
4485                     // We have a pending remove operation, which is holding the
4486                     // last unstable reference.  At this point we are converting
4487                     // that unstable reference to our new stable reference.
4488                     unstableDelta = -1;
4489                     // Cancel the removal of the provider.
4490                     if (DEBUG_PROVIDER) {
4491                         Slog.v(TAG, "incProviderRef: stable "
4492                                 + "snatched provider from the jaws of death");
4493                     }
4494                     prc.removePending = false;
4495                     mH.removeMessages(H.REMOVE_PROVIDER, prc);
4496                 } else {
4497                     unstableDelta = 0;
4498                 }
4499                 try {
4500                     if (DEBUG_PROVIDER) {
4501                         Slog.v(TAG, "incProviderRef Now stable - "
4502                                 + prc.holder.info.name + ": unstableDelta="
4503                                 + unstableDelta);
4504                     }
4505                     ActivityManagerNative.getDefault().refContentProvider(
4506                             prc.holder.connection, 1, unstableDelta);
4507                 } catch (RemoteException e) {
4508                     //do nothing content provider object is dead any way
4509                 }
4510             }
4511         } else {
4512             prc.unstableCount += 1;
4513             if (prc.unstableCount == 1) {
4514                 // We are acquiring a new unstable reference on the provider.
4515                 if (prc.removePending) {
4516                     // Oh look, we actually have a remove pending for the
4517                     // provider, which is still holding the last unstable
4518                     // reference.  We just need to cancel that to take new
4519                     // ownership of the reference.
4520                     if (DEBUG_PROVIDER) {
4521                         Slog.v(TAG, "incProviderRef: unstable "
4522                                 + "snatched provider from the jaws of death");
4523                     }
4524                     prc.removePending = false;
4525                     mH.removeMessages(H.REMOVE_PROVIDER, prc);
4526                 } else {
4527                     // First unstable ref, increment our count in the
4528                     // activity manager.
4529                     try {
4530                         if (DEBUG_PROVIDER) {
4531                             Slog.v(TAG, "incProviderRef: Now unstable - "
4532                                     + prc.holder.info.name);
4533                         }
4534                         ActivityManagerNative.getDefault().refContentProvider(
4535                                 prc.holder.connection, 0, 1);
4536                     } catch (RemoteException e) {
4537                         //do nothing content provider object is dead any way
4538                     }
4539                 }
4540             }
4541         }
4542     }
4543
4544     public final IContentProvider acquireExistingProvider(
4545             Context c, String auth, int userId, boolean stable) {
4546         synchronized (mProviderMap) {
4547             final ProviderKey key = new ProviderKey(auth, userId);
4548             final ProviderClientRecord pr = mProviderMap.get(key);
4549             if (pr == null) {
4550                 return null;
4551             }
4552
4553             IContentProvider provider = pr.mProvider;
4554             IBinder jBinder = provider.asBinder();
4555             if (!jBinder.isBinderAlive()) {
4556                 // The hosting process of the provider has died; we can't
4557                 // use this one.
4558                 Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
4559                         + ": existing object's process dead");
4560                 handleUnstableProviderDiedLocked(jBinder, true);
4561                 return null;
4562             }
4563
4564             // Only increment the ref count if we have one.  If we don't then the
4565             // provider is not reference counted and never needs to be released.
4566             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4567             if (prc != null) {
4568                 incProviderRefLocked(prc, stable);
4569             }
4570             return provider;
4571         }
4572     }
4573
4574     public final boolean releaseProvider(IContentProvider provider, boolean stable) {
4575         if (provider == null) {
4576             return false;
4577         }
4578
4579         IBinder jBinder = provider.asBinder();
4580         synchronized (mProviderMap) {
4581             ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4582             if (prc == null) {
4583                 // The provider has no ref count, no release is needed.
4584                 return false;
4585             }
4586
4587             boolean lastRef = false;
4588             if (stable) {
4589                 if (prc.stableCount == 0) {
4590                     if (DEBUG_PROVIDER) Slog.v(TAG,
4591                             "releaseProvider: stable ref count already 0, how?");
4592                     return false;
4593                 }
4594                 prc.stableCount -= 1;
4595                 if (prc.stableCount == 0) {
4596                     // What we do at this point depends on whether there are
4597                     // any unstable refs left: if there are, we just tell the
4598                     // activity manager to decrement its stable count; if there
4599                     // aren't, we need to enqueue this provider to be removed,
4600                     // and convert to holding a single unstable ref while
4601                     // doing so.
4602                     lastRef = prc.unstableCount == 0;
4603                     try {
4604                         if (DEBUG_PROVIDER) {
4605                             Slog.v(TAG, "releaseProvider: No longer stable w/lastRef="
4606                                     + lastRef + " - " + prc.holder.info.name);
4607                         }
4608                         ActivityManagerNative.getDefault().refContentProvider(
4609                                 prc.holder.connection, -1, lastRef ? 1 : 0);
4610                     } catch (RemoteException e) {
4611                         //do nothing content provider object is dead any way
4612                     }
4613                 }
4614             } else {
4615                 if (prc.unstableCount == 0) {
4616                     if (DEBUG_PROVIDER) Slog.v(TAG,
4617                             "releaseProvider: unstable ref count already 0, how?");
4618                     return false;
4619                 }
4620                 prc.unstableCount -= 1;
4621                 if (prc.unstableCount == 0) {
4622                     // If this is the last reference, we need to enqueue
4623                     // this provider to be removed instead of telling the
4624                     // activity manager to remove it at this point.
4625                     lastRef = prc.stableCount == 0;
4626                     if (!lastRef) {
4627                         try {
4628                             if (DEBUG_PROVIDER) {
4629                                 Slog.v(TAG, "releaseProvider: No longer unstable - "
4630                                         + prc.holder.info.name);
4631                             }
4632                             ActivityManagerNative.getDefault().refContentProvider(
4633                                     prc.holder.connection, 0, -1);
4634                         } catch (RemoteException e) {
4635                             //do nothing content provider object is dead any way
4636                         }
4637                     }
4638                 }
4639             }
4640
4641             if (lastRef) {
4642                 if (!prc.removePending) {
4643                     // Schedule the actual remove asynchronously, since we don't know the context
4644                     // this will be called in.
4645                     // TODO: it would be nice to post a delayed message, so
4646                     // if we come back and need the same provider quickly
4647                     // we will still have it available.
4648                     if (DEBUG_PROVIDER) {
4649                         Slog.v(TAG, "releaseProvider: Enqueueing pending removal - "
4650                                 + prc.holder.info.name);
4651                     }
4652                     prc.removePending = true;
4653                     Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
4654                     mH.sendMessage(msg);
4655                 } else {
4656                     Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
4657                 }
4658             }
4659             return true;
4660         }
4661     }
4662
4663     final void completeRemoveProvider(ProviderRefCount prc) {
4664         synchronized (mProviderMap) {
4665             if (!prc.removePending) {
4666                 // There was a race!  Some other client managed to acquire
4667                 // the provider before the removal was completed.
4668                 // Abort the removal.  We will do it later.
4669                 if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, "
4670                         + "provider still in use");
4671                 return;
4672             }
4673
4674             final IBinder jBinder = prc.holder.provider.asBinder();
4675             ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
4676             if (existingPrc == prc) {
4677                 mProviderRefCountMap.remove(jBinder);
4678             }
4679
4680             Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
4681             while (iter.hasNext()) {
4682                 ProviderClientRecord pr = iter.next();
4683                 IBinder myBinder = pr.mProvider.asBinder();
4684                 if (myBinder == jBinder) {
4685                     iter.remove();
4686                 }
4687             }
4688         }
4689
4690         try {
4691             if (DEBUG_PROVIDER) {
4692                 Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative."
4693                         + "removeContentProvider(" + prc.holder.info.name + ")");
4694             }
4695             ActivityManagerNative.getDefault().removeContentProvider(
4696                     prc.holder.connection, false);
4697         } catch (RemoteException e) {
4698             //do nothing content provider object is dead any way
4699         }
4700     }
4701
4702     final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
4703         synchronized (mProviderMap) {
4704             handleUnstableProviderDiedLocked(provider, fromClient);
4705         }
4706     }
4707
4708     final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) {
4709         ProviderRefCount prc = mProviderRefCountMap.get(provider);
4710         if (prc != null) {
4711             if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
4712                     + provider + " " + prc.holder.info.name);
4713             mProviderRefCountMap.remove(provider);
4714             if (prc.client != null && prc.client.mNames != null) {
4715                 for (String name : prc.client.mNames) {
4716                     ProviderClientRecord pr = mProviderMap.get(name);
4717                     if (pr != null && pr.mProvider.asBinder() == provider) {
4718                         Slog.i(TAG, "Removing dead content provider: " + name);
4719                         mProviderMap.remove(name);
4720                     }
4721                 }
4722             }
4723             if (fromClient) {
4724                 // We found out about this due to execution in our client
4725                 // code.  Tell the activity manager about it now, to ensure
4726                 // that the next time we go to do anything with the provider
4727                 // it knows it is dead (so we don't race with its death
4728                 // notification).
4729                 try {
4730                     ActivityManagerNative.getDefault().unstableProviderDied(
4731                             prc.holder.connection);
4732                 } catch (RemoteException e) {
4733                     //do nothing content provider object is dead any way
4734                 }
4735             }
4736         }
4737     }
4738
4739     private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
4740             ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {
4741         final String auths[] = PATTERN_SEMICOLON.split(holder.info.authority);
4742         final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
4743
4744         final ProviderClientRecord pcr = new ProviderClientRecord(
4745                 auths, provider, localProvider, holder);
4746         for (String auth : auths) {
4747             final ProviderKey key = new ProviderKey(auth, userId);
4748             final ProviderClientRecord existing = mProviderMap.get(key);
4749             if (existing != null) {
4750                 Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
4751                         + " already published as " + auth);
4752             } else {
4753                 mProviderMap.put(key, pcr);
4754             }
4755         }
4756         return pcr;
4757     }
4758
4759     /**
4760      * Installs the provider.
4761      *
4762      * Providers that are local to the process or that come from the system server
4763      * may be installed permanently which is indicated by setting noReleaseNeeded to true.
4764      * Other remote providers are reference counted.  The initial reference count
4765      * for all reference counted providers is one.  Providers that are not reference
4766      * counted do not have a reference count (at all).
4767      *
4768      * This method detects when a provider has already been installed.  When this happens,
4769      * it increments the reference count of the existing provider (if appropriate)
4770      * and returns the existing provider.  This can happen due to concurrent
4771      * attempts to acquire the same provider.
4772      */
4773     private IActivityManager.ContentProviderHolder installProvider(Context context,
4774             IActivityManager.ContentProviderHolder holder, ProviderInfo info,
4775             boolean noisy, boolean noReleaseNeeded, boolean stable) {
4776         ContentProvider localProvider = null;
4777         IContentProvider provider;
4778         if (holder == null || holder.provider == null) {
4779             if (DEBUG_PROVIDER || noisy) {
4780                 Slog.d(TAG, "Loading provider " + info.authority + ": "
4781                         + info.name);
4782             }
4783             Context c = null;
4784             ApplicationInfo ai = info.applicationInfo;
4785             if (context.getPackageName().equals(ai.packageName)) {
4786                 c = context;
4787             } else if (mInitialApplication != null &&
4788                     mInitialApplication.getPackageName().equals(ai.packageName)) {
4789                 c = mInitialApplication;
4790             } else {
4791                 try {
4792                     c = context.createPackageContext(ai.packageName,
4793                             Context.CONTEXT_INCLUDE_CODE);
4794                 } catch (PackageManager.NameNotFoundException e) {
4795                     // Ignore
4796                 }
4797             }
4798             if (c == null) {
4799                 Slog.w(TAG, "Unable to get context for package " +
4800                       ai.packageName +
4801                       " while loading content provider " +
4802                       info.name);
4803                 return null;
4804             }
4805             try {
4806                 final java.lang.ClassLoader cl = c.getClassLoader();
4807                 localProvider = (ContentProvider)cl.
4808                     loadClass(info.name).newInstance();
4809                 provider = localProvider.getIContentProvider();
4810                 if (provider == null) {
4811                     Slog.e(TAG, "Failed to instantiate class " +
4812                           info.name + " from sourceDir " +
4813                           info.applicationInfo.sourceDir);
4814                     return null;
4815                 }
4816                 if (DEBUG_PROVIDER) Slog.v(
4817                     TAG, "Instantiating local provider " + info.name);
4818                 // XXX Need to create the correct context for this provider.
4819                 localProvider.attachInfo(c, info);
4820             } catch (java.lang.Exception e) {
4821                 if (!mInstrumentation.onException(null, e)) {
4822                     throw new RuntimeException(
4823                             "Unable to get provider " + info.name
4824                             + ": " + e.toString(), e);
4825                 }
4826                 return null;
4827             }
4828         } else {
4829             provider = holder.provider;
4830             if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
4831                     + info.name);
4832         }
4833
4834         IActivityManager.ContentProviderHolder retHolder;
4835
4836         synchronized (mProviderMap) {
4837             if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
4838                     + " / " + info.name);
4839             IBinder jBinder = provider.asBinder();
4840             if (localProvider != null) {
4841                 ComponentName cname = new ComponentName(info.packageName, info.name);
4842                 ProviderClientRecord pr = mLocalProvidersByName.get(cname);
4843                 if (pr != null) {
4844                     if (DEBUG_PROVIDER) {
4845                         Slog.v(TAG, "installProvider: lost the race, "
4846                                 + "using existing local provider");
4847                     }
4848                     provider = pr.mProvider;
4849                 } else {
4850                     holder = new IActivityManager.ContentProviderHolder(info);
4851                     holder.provider = provider;
4852                     holder.noReleaseNeeded = true;
4853                     pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
4854                     mLocalProviders.put(jBinder, pr);
4855                     mLocalProvidersByName.put(cname, pr);
4856                 }
4857                 retHolder = pr.mHolder;
4858             } else {
4859                 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4860                 if (prc != null) {
4861                     if (DEBUG_PROVIDER) {
4862                         Slog.v(TAG, "installProvider: lost the race, updating ref count");
4863                     }
4864                     // We need to transfer our new reference to the existing
4865                     // ref count, releasing the old one...  but only if
4866                     // release is needed (that is, it is not running in the
4867                     // system process).
4868                     if (!noReleaseNeeded) {
4869                         incProviderRefLocked(prc, stable);
4870                         try {
4871                             ActivityManagerNative.getDefault().removeContentProvider(
4872                                     holder.connection, stable);
4873                         } catch (RemoteException e) {
4874                             //do nothing content provider object is dead any way
4875                         }
4876                     }
4877                 } else {
4878                     ProviderClientRecord client = installProviderAuthoritiesLocked(
4879                             provider, localProvider, holder);
4880                     if (noReleaseNeeded) {
4881                         prc = new ProviderRefCount(holder, client, 1000, 1000);
4882                     } else {
4883                         prc = stable
4884                                 ? new ProviderRefCount(holder, client, 1, 0)
4885                                 : new ProviderRefCount(holder, client, 0, 1);
4886                     }
4887                     mProviderRefCountMap.put(jBinder, prc);
4888                 }
4889                 retHolder = prc.holder;
4890             }
4891         }
4892
4893         return retHolder;
4894     }
4895
4896     private void attach(boolean system) {
4897         sThreadLocal.set(this);
4898         mSystemThread = system;
4899         if (!system) {
4900             ViewRootImpl.addFirstDrawHandler(new Runnable() {
4901                 public void run() {
4902                     ensureJitEnabled();
4903                 }
4904             });
4905             android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
4906                                                     UserHandle.myUserId());
4907             RuntimeInit.setApplicationObject(mAppThread.asBinder());
4908             IActivityManager mgr = ActivityManagerNative.getDefault();
4909             try {
4910                 mgr.attachApplication(mAppThread);
4911             } catch (RemoteException ex) {
4912                 // Ignore
4913             }
4914         } else {
4915             // Don't set application object here -- if the system crashes,
4916             // we can't display an alert, we just want to die die die.
4917             android.ddm.DdmHandleAppName.setAppName("system_process",
4918                                                     UserHandle.myUserId());
4919             try {
4920                 mInstrumentation = new Instrumentation();
4921                 ContextImpl context = new ContextImpl();
4922                 context.init(getSystemContext().mPackageInfo, null, this);
4923                 Application app = Instrumentation.newApplication(Application.class, context);
4924                 mAllApplications.add(app);
4925                 mInitialApplication = app;
4926                 app.onCreate();
4927             } catch (Exception e) {
4928                 throw new RuntimeException(
4929                         "Unable to instantiate Application():" + e.toString(), e);
4930             }
4931         }
4932
4933         // add dropbox logging to libcore
4934         DropBox.setReporter(new DropBoxReporter());
4935
4936         ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
4937             public void onConfigurationChanged(Configuration newConfig) {
4938                 synchronized (mPackages) {
4939                     // We need to apply this change to the resources
4940                     // immediately, because upon returning the view
4941                     // hierarchy will be informed about it.
4942                     if (applyConfigurationToResourcesLocked(newConfig, null)) {
4943                         // This actually changed the resources!  Tell
4944                         // everyone about it.
4945                         if (mPendingConfiguration == null ||
4946                                 mPendingConfiguration.isOtherSeqNewer(newConfig)) {
4947                             mPendingConfiguration = newConfig;
4948                             
4949                             queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
4950                         }
4951                     }
4952                 }
4953             }
4954             public void onLowMemory() {
4955             }
4956             public void onTrimMemory(int level) {
4957             }
4958         });
4959     }
4960
4961     public static ActivityThread systemMain() {
4962         HardwareRenderer.disable(true);
4963         ActivityThread thread = new ActivityThread();
4964         thread.attach(true);
4965         return thread;
4966     }
4967
4968     public final void installSystemProviders(List<ProviderInfo> providers) {
4969         if (providers != null) {
4970             installContentProviders(mInitialApplication, providers);
4971         }
4972     }
4973
4974     public int getIntCoreSetting(String key, int defaultValue) {
4975         synchronized (mPackages) {
4976             if (mCoreSettings != null) {
4977                 return mCoreSettings.getInt(key, defaultValue);
4978             } else {
4979                 return defaultValue;
4980             }
4981         }
4982     }
4983
4984     private static class EventLoggingReporter implements EventLogger.Reporter {
4985         @Override
4986         public void report (int code, Object... list) {
4987             EventLog.writeEvent(code, list);
4988         }
4989     }
4990
4991     private class DropBoxReporter implements DropBox.Reporter {
4992
4993         private DropBoxManager dropBox;
4994
4995         public DropBoxReporter() {
4996             dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
4997         }
4998
4999         @Override
5000         public void addData(String tag, byte[] data, int flags) {
5001             dropBox.addData(tag, data, flags);
5002         }
5003
5004         @Override
5005         public void addText(String tag, String data) {
5006             dropBox.addText(tag, data);
5007         }
5008     }
5009
5010     public static void main(String[] args) {
5011         SamplingProfilerIntegration.start();
5012
5013         // CloseGuard defaults to true and can be quite spammy.  We
5014         // disable it here, but selectively enable it later (via
5015         // StrictMode) on debug builds, but using DropBox, not logs.
5016         CloseGuard.setEnabled(false);
5017
5018         Environment.initForCurrentUser();
5019
5020         // Set the reporter for event logging in libcore
5021         EventLogger.setReporter(new EventLoggingReporter());
5022
5023         Process.setArgV0("<pre-initialized>");
5024
5025         Looper.prepareMainLooper();
5026
5027         ActivityThread thread = new ActivityThread();
5028         thread.attach(false);
5029
5030         if (sMainThreadHandler == null) {
5031             sMainThreadHandler = thread.getHandler();
5032         }
5033
5034         AsyncTask.init();
5035
5036         if (false) {
5037             Looper.myLooper().setMessageLogging(new
5038                     LogPrinter(Log.DEBUG, "ActivityThread"));
5039         }
5040
5041         Looper.loop();
5042
5043         throw new RuntimeException("Main thread loop unexpectedly exited");
5044     }
5045 }